cutils.pas 46 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements some support functions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {# This unit contains some generic support functions which are used
  18. in the different parts of the compiler.
  19. }
  20. unit cutils;
  21. {$i fpcdefs.inc}
  22. interface
  23. uses
  24. constexp;
  25. type
  26. Tcharset=set of char;
  27. var
  28. internalerrorproc : procedure(i:longint);
  29. {# Returns the minimal value between @var(a) and @var(b) }
  30. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  31. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  32. function min(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  33. {# Returns the maximum value between @var(a) and @var(b) }
  34. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  35. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  36. function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  37. { These functions are intenionally put here and not in the constexp unit.
  38. Since Tconstexprint may be automatically converted to int, which causes
  39. loss of data and since there are already min and max functions for ints in
  40. this unit, we put min and max for Tconstexprint as well. This way we avoid
  41. potential bugs, caused by code unintentionally calling the int versions of
  42. min/max on Tconstexprint, because of only including cutils and forgetting
  43. the constexp unit in the uses clause. }
  44. function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  45. function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  46. {# Return value @var(i) aligned on @var(a) boundary }
  47. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  48. function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
  49. function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
  50. { if you have an address aligned using "oldalignment" and add an
  51. offset of (a multiple of) offset to it, this function calculates
  52. the new minimally guaranteed alignment
  53. }
  54. function newalignment(oldalignment: longint; offset: int64): longint;
  55. {# Return @var(b) with the bit order reversed }
  56. function reverse_byte(b: byte): byte;
  57. {# Return @var(w) with the bit order reversed }
  58. function reverse_word(w: word): word;
  59. {# Return @var(l) with the bit order reversed }
  60. function reverse_longword(l: longword): longword;
  61. function next_prime(l: longint): longint;
  62. function used_align(varalign,minalign,maxalign:longint):longint;
  63. function isbetteralignedthan(new, org, limit: cardinal): boolean;
  64. function packedbitsloadsize(bitlen: int64) : int64;
  65. procedure Replace(var s:string;s1:string;const s2:string);
  66. procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
  67. procedure ReplaceCase(var s:string;const s1,s2:string);
  68. procedure ReplaceCase(var s:ansistring;const s1,s2:ansistring);
  69. Function MatchPattern(const pattern,what:string):boolean;
  70. function upper(const c : char) : char;
  71. function upper(const s : string) : string;
  72. function upper(const s : ansistring) : ansistring;
  73. function lower(const c : char) : char;
  74. function lower(const s : string) : string;
  75. function lower(const s : ansistring) : ansistring;
  76. function rpos(const needle: char; const haystack: shortstring): longint; overload;
  77. function rpos(const needle: shortstring; const haystack: shortstring): longint; overload;
  78. function trimspace(const s:string):string;
  79. function trimspace(const s:AnsiString):AnsiString;
  80. function space (b : longint): string;
  81. { returns the position of the first char of the set cs in s, if there is none, then it returns 0 }
  82. function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
  83. function PadSpace(const s:string;len:longint):string;
  84. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  85. function GetToken(var s:string;endchar:char):string;
  86. function GetToken(var s:ansistring;endchar:char):ansistring;
  87. procedure uppervar(var s : string);
  88. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  89. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  90. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  91. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  92. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  93. function DStr(l:longint):string;
  94. {# Returns true if the string s is a number }
  95. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  96. {# Returns true if value is a power of 2, the actual
  97. exponent value is returned in power.
  98. }
  99. function ispowerof2(value : int64;out power : longint) : boolean;
  100. function ispowerof2(const value : Tconstexprint;out power : longint) : boolean;
  101. {# Returns true if abs(value) is a power of 2, the actual
  102. exponent value is returned in power.
  103. }
  104. function isabspowerof2(const value : Tconstexprint; out power : longint) : boolean;
  105. { # Returns the power of 2 >= value }
  106. function nextpowerof2(value : qword; out power: longint) : qword;
  107. function backspace_quote(const s:string;const qchars:Tcharset):string;
  108. function octal_quote(const s:string;const qchars:Tcharset):string;
  109. {# If the string is quoted, in accordance with pascal, it is
  110. dequoted and returned in s, and the function returns true.
  111. If it is not quoted, or if the quoting is bad, s is not touched,
  112. and false is returned.
  113. }
  114. function DePascalQuote(var s: ansistring): Boolean;
  115. function CompareStr(const S1, S2: string): Integer;
  116. function CompareText(S1, S2: string): integer;
  117. function CompareVersionStrings(s1,s2: string): longint;
  118. { releases the string p and assignes nil to p }
  119. { if p=nil then freemem isn't called }
  120. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  121. { allocates mem for a copy of s, copies s to this mem and returns }
  122. { a pointer to this mem }
  123. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  124. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  125. {# Allocates memory for the string @var(s) and copies s as zero
  126. terminated string to that allocated memory and returns a pointer
  127. to that mem
  128. }
  129. function strpnew(const s : string) : pchar;
  130. function strpnew(const s : ansistring) : pchar;
  131. {# makes the character @var(c) lowercase, with spanish, french and german
  132. character set
  133. }
  134. function lowercase(c : char) : char;
  135. { makes zero terminated string to a pascal string }
  136. { the data in p is modified and p is returned }
  137. function pchar2pshortstring(p : pchar) : pshortstring;
  138. { inverse of pchar2pshortstring }
  139. function pshortstring2pchar(p : pshortstring) : pchar;
  140. { allocate a new pchar with the contents of a}
  141. function ansistring2pchar(const a: ansistring) : pchar;
  142. { Ansistring (pchar+length) support }
  143. procedure ansistringdispose(var p : pchar;length : longint);
  144. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  145. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  146. {Lzw encode/decode to compress strings -> save memory.}
  147. function minilzw_encode(const s:string):string;
  148. function minilzw_decode(const s:string):string;
  149. Function nextafter(x,y:double):double;
  150. function LengthUleb128(a: qword) : byte;
  151. function LengthSleb128(a: int64) : byte;
  152. function EncodeUleb128(a: qword;out buf;len: byte) : byte;
  153. function EncodeSleb128(a: int64;out buf;len: byte) : byte;
  154. { hide Sysutils.ExecuteProcess in units using this one after SysUtils}
  155. const
  156. ExecuteProcess = 'Do not use' deprecated 'Use cfileutil.RequotedExecuteProcess instead, ExecuteProcess cannot deal with single quotes as used by Unix command lines';
  157. implementation
  158. uses
  159. SysUtils;
  160. var
  161. uppertbl,
  162. lowertbl : array[char] of char;
  163. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  164. {
  165. return the minimal of a and b
  166. }
  167. begin
  168. if a<=b then
  169. min:=a
  170. else
  171. min:=b;
  172. end;
  173. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  174. {
  175. return the minimal of a and b
  176. }
  177. begin
  178. if a<=b then
  179. min:=a
  180. else
  181. min:=b;
  182. end;
  183. function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  184. {
  185. return the minimal of a and b
  186. }
  187. begin
  188. if a<=b then
  189. min:=a
  190. else
  191. min:=b;
  192. end;
  193. function min(a,b : qword) : qword;
  194. {
  195. return the minimal of a and b
  196. }
  197. begin
  198. if a<=b then
  199. min:=a
  200. else
  201. min:=b;
  202. end;
  203. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  204. {
  205. return the maximum of a and b
  206. }
  207. begin
  208. if a>=b then
  209. max:=a
  210. else
  211. max:=b;
  212. end;
  213. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  214. {
  215. return the maximum of a and b
  216. }
  217. begin
  218. if a>=b then
  219. max:=a
  220. else
  221. max:=b;
  222. end;
  223. function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  224. {
  225. return the maximum of a and b
  226. }
  227. begin
  228. if a>=b then
  229. max:=a
  230. else
  231. max:=b;
  232. end;
  233. function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  234. {
  235. return the maximum of a and b
  236. }
  237. begin
  238. if a>=b then
  239. max:=a
  240. else
  241. max:=b;
  242. end;
  243. function newalignment(oldalignment: longint; offset: int64): longint;
  244. begin
  245. { oldalignment must be power of two.
  246. Negating two's complement number keeps its tail '100...000' and complements all bits above.
  247. "x and -x" extracts this tail of 'x'.
  248. Said tail of "oldalignment or offset" is the desired answer. }
  249. result:=oldalignment or longint(offset); { high part of offset won't matter as long as alignment is 32-bit }
  250. result:=result and -result;
  251. end;
  252. function reverse_byte(b: byte): byte;
  253. const
  254. reverse_nible:array[0..15] of 0..15 =
  255. (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
  256. %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
  257. begin
  258. reverse_byte:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
  259. end;
  260. function reverse_word(w: word): word;
  261. type
  262. TWordRec = packed record
  263. hi, lo: Byte;
  264. end;
  265. begin
  266. TWordRec(reverse_word).hi := reverse_byte(TWordRec(w).lo);
  267. TWordRec(reverse_word).lo := reverse_byte(TWordRec(w).hi);
  268. end;
  269. function reverse_longword(l: longword): longword;
  270. type
  271. TLongWordRec = packed record
  272. b: array[0..3] of Byte;
  273. end;
  274. begin
  275. TLongWordRec(reverse_longword).b[0] := reverse_byte(TLongWordRec(l).b[3]);
  276. TLongWordRec(reverse_longword).b[1] := reverse_byte(TLongWordRec(l).b[2]);
  277. TLongWordRec(reverse_longword).b[2] := reverse_byte(TLongWordRec(l).b[1]);
  278. TLongWordRec(reverse_longword).b[3] := reverse_byte(TLongWordRec(l).b[0]);
  279. end;
  280. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  281. {
  282. return value <i> aligned <a> boundary. <a> must be power of two.
  283. }
  284. begin
  285. { One-line formula for i >= 0 is
  286. >>> (i + a - 1) and not (a - 1),
  287. and for i < 0 is
  288. >>> i and not (a - 1). }
  289. if a>0 then
  290. a:=a-1; { 'a' is decremented beforehand, this also allows a=0 as a synonym for a=1. }
  291. if i>=0 then
  292. i:=i+a;
  293. result:=i and not a;
  294. end;
  295. function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
  296. {
  297. return value <i> aligned <a> boundary. <a> must be power of two.
  298. }
  299. begin
  300. { Copy of 'longint' version. }
  301. if a>0 then
  302. a:=a-1;
  303. if i>=0 then
  304. i:=i+a;
  305. result:=i and not a;
  306. end;
  307. function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
  308. {
  309. return value <i> aligned <a> boundary. <a> must be power of two.
  310. }
  311. begin
  312. { No i < 0 case here. }
  313. if a>0 then
  314. a:=a-1;
  315. result:=(i+a) and not a;
  316. end;
  317. function packedbitsloadsize(bitlen: int64) : int64;
  318. begin
  319. case bitlen of
  320. 1,2,4,8:
  321. result := 1;
  322. { 10 bits can never be split over 3 bytes via 1-8-1, because it }
  323. { always starts at a multiple of 10 bits. Same for the others. }
  324. 3,5,6,7,9,10,12,16:
  325. result := 2;
  326. {$ifdef cpu64bitalu}
  327. { performance penalty for unaligned 8 byte access is much }
  328. { higher than for unaligned 4 byte access, at least on ppc, }
  329. { so use 4 bytes even in some cases where a value could }
  330. { always loaded using a single 8 byte load (e.g. in case of }
  331. { 28 bit values) }
  332. 11,13,14,15,17..32:
  333. result := 4;
  334. else
  335. result := 8;
  336. {$else cpu64bitalu}
  337. else
  338. result := 4;
  339. {$endif cpu64bitalu}
  340. end;
  341. end;
  342. function isbetteralignedthan(new, org, limit: cardinal): boolean;
  343. var
  344. cnt: cardinal;
  345. begin
  346. cnt:=2;
  347. while (cnt <= limit) do
  348. begin
  349. if (org and (cnt-1)) > (new and (cnt-1)) then
  350. begin
  351. result:=true;
  352. exit;
  353. end
  354. else if (org and (cnt-1)) < (new and (cnt-1)) then
  355. begin
  356. result:=false;
  357. exit;
  358. end;
  359. cnt:=cnt*2;
  360. end;
  361. result:=false;
  362. end;
  363. function next_prime(l: longint): longint;
  364. var
  365. check, checkbound: longint;
  366. ok: boolean;
  367. begin
  368. result:=l or 1;
  369. while l<high(longint) do
  370. begin
  371. ok:=true;
  372. checkbound:=trunc(sqrt(l));
  373. check:=3;
  374. while check<checkbound do
  375. begin
  376. if (l mod check) = 0 then
  377. begin
  378. ok:=false;
  379. break;
  380. end;
  381. inc(check,2);
  382. end;
  383. if ok then
  384. exit;
  385. inc(l);
  386. end;
  387. end;
  388. function used_align(varalign,minalign,maxalign:longint):longint;
  389. begin
  390. { varalign : minimum alignment required for the variable
  391. minalign : Minimum alignment of this structure, 0 = undefined
  392. maxalign : Maximum alignment of this structure, 0 = undefined }
  393. if (minalign>0) and
  394. (varalign<=minalign) then
  395. used_align:=minalign
  396. else
  397. begin
  398. if (maxalign>0) and
  399. (varalign>maxalign) then
  400. used_align:=maxalign
  401. else
  402. used_align:=varalign;
  403. end;
  404. end;
  405. procedure Replace(var s:string;s1:string;const s2:string);
  406. var
  407. last,
  408. i : longint;
  409. begin
  410. s1:=upper(s1);
  411. last:=0;
  412. repeat
  413. i:=pos(s1,upper(s));
  414. if i=last then
  415. i:=0;
  416. if (i>0) then
  417. begin
  418. Delete(s,i,length(s1));
  419. Insert(s2,s,i);
  420. last:=i;
  421. end;
  422. until (i=0);
  423. end;
  424. procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
  425. var
  426. last,
  427. i : longint;
  428. begin
  429. s1:=upper(s1);
  430. last:=0;
  431. repeat
  432. i:=pos(s1,upper(s));
  433. if i=last then
  434. i:=0;
  435. if (i>0) then
  436. begin
  437. Delete(s,i,length(s1));
  438. Insert(s2,s,i);
  439. last:=i;
  440. end;
  441. until (i=0);
  442. end;
  443. procedure ReplaceCase(var s:string;const s1,s2:string);
  444. var
  445. last,
  446. i : longint;
  447. begin
  448. last:=0;
  449. repeat
  450. i:=pos(s1,s);
  451. if i=last then
  452. i:=0;
  453. if (i>0) then
  454. begin
  455. Delete(s,i,length(s1));
  456. Insert(s2,s,i);
  457. last:=i;
  458. end;
  459. until (i=0);
  460. end;
  461. procedure ReplaceCase(var s: ansistring; const s1, s2: ansistring);
  462. var
  463. last,
  464. i : longint;
  465. begin
  466. last:=0;
  467. repeat
  468. i:=pos(s1,s);
  469. if i=last then
  470. i:=0;
  471. if (i>0) then
  472. begin
  473. Delete(s,i,length(s1));
  474. Insert(s2,s,i);
  475. last:=i;
  476. end;
  477. until (i=0);
  478. end;
  479. Function MatchPattern(const pattern,what:string):boolean;
  480. var
  481. found : boolean;
  482. i1,i2 : longint;
  483. begin
  484. i1:=0;
  485. i2:=0;
  486. if pattern='' then
  487. begin
  488. result:=(what='');
  489. exit;
  490. end;
  491. found:=true;
  492. repeat
  493. inc(i1);
  494. if (i1>length(pattern)) then
  495. break;
  496. inc(i2);
  497. if (i2>length(what)) then
  498. break;
  499. case pattern[i1] of
  500. '?' :
  501. found:=true;
  502. '*' :
  503. begin
  504. found:=true;
  505. if (i1=length(pattern)) then
  506. i2:=length(what)
  507. else
  508. if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
  509. begin
  510. if i2<length(what) then
  511. dec(i1)
  512. end
  513. else
  514. if i2>1 then
  515. dec(i2);
  516. end;
  517. else
  518. found:=(pattern[i1]=what[i2]) or (what[i2]='?');
  519. end;
  520. until not found;
  521. if found then
  522. begin
  523. found:=(i2>=length(what)) and
  524. (
  525. (i1>length(pattern)) or
  526. ((i1=length(pattern)) and
  527. (pattern[i1]='*'))
  528. );
  529. end;
  530. result:=found;
  531. end;
  532. function upper(const c : char) : char;
  533. {
  534. return uppercase of c
  535. }
  536. begin
  537. upper:=uppertbl[c];
  538. end;
  539. function upper(const s : string) : string;
  540. {
  541. return uppercased string of s
  542. }
  543. var
  544. i : longint;
  545. begin
  546. for i:=1 to length(s) do
  547. upper[i]:=uppertbl[s[i]];
  548. upper[0]:=s[0];
  549. end;
  550. function upper(const s : ansistring) : ansistring;
  551. {
  552. return uppercased string of s
  553. }
  554. var
  555. i : longint;
  556. begin
  557. Result:='';
  558. setlength(upper,length(s));
  559. for i:=1 to length(s) do
  560. upper[i]:=uppertbl[s[i]];
  561. end;
  562. function lower(const c : char) : char;
  563. {
  564. return lowercase of c
  565. }
  566. begin
  567. lower:=lowertbl[c];
  568. end;
  569. function lower(const s : string) : string;
  570. {
  571. return lowercased string of s
  572. }
  573. var
  574. i : longint;
  575. begin
  576. for i:=1 to length(s) do
  577. lower[i]:=lowertbl[s[i]];
  578. lower[0]:=s[0];
  579. end;
  580. function lower(const s : ansistring) : ansistring;
  581. {
  582. return lowercased string of s
  583. }
  584. var
  585. i : longint;
  586. begin
  587. Result:='';
  588. setlength(lower,length(s));
  589. for i:=1 to length(s) do
  590. lower[i]:=lowertbl[s[i]];
  591. end;
  592. procedure uppervar(var s : string);
  593. {
  594. uppercase string s
  595. }
  596. var
  597. i : longint;
  598. begin
  599. for i:=1 to length(s) do
  600. s[i]:=uppertbl[s[i]];
  601. end;
  602. procedure initupperlower;
  603. var
  604. c : char;
  605. begin
  606. for c:=#0 to #255 do
  607. begin
  608. lowertbl[c]:=c;
  609. uppertbl[c]:=c;
  610. case c of
  611. 'A'..'Z' :
  612. lowertbl[c]:=char(byte(c)+32);
  613. 'a'..'z' :
  614. uppertbl[c]:=char(byte(c)-32);
  615. end;
  616. end;
  617. end;
  618. function DStr(l:longint):string;
  619. var
  620. TmpStr : string[32];
  621. i : longint;
  622. begin
  623. Str(l,TmpStr);
  624. i:=Length(TmpStr);
  625. while (i>3) do
  626. begin
  627. dec(i,3);
  628. if TmpStr[i]<>'-' then
  629. insert('.',TmpStr,i+1);
  630. end;
  631. DStr:=TmpStr;
  632. end;
  633. function rpos(const needle: char; const haystack: shortstring): longint;
  634. begin
  635. result:=length(haystack);
  636. while (result>0) do
  637. begin
  638. if haystack[result]=needle then
  639. exit;
  640. dec(result);
  641. end;
  642. end;
  643. function rpos(const needle: shortstring; const haystack: shortstring): longint;
  644. begin
  645. result:=0;
  646. if (length(needle)=0) or
  647. (length(needle)>length(haystack)) then
  648. exit;
  649. result:=length(haystack)-length(needle);
  650. repeat
  651. if (haystack[result]=needle[1]) and
  652. (copy(haystack,result,length(needle))=needle) then
  653. exit;
  654. dec(result);
  655. until result=0;
  656. end;
  657. function trimspace(const s:string):string;
  658. {
  659. return s with all leading and ending spaces and tabs removed
  660. }
  661. var
  662. i,j : longint;
  663. begin
  664. i:=length(s);
  665. while (i>0) and (s[i] in [#9,' ']) do
  666. dec(i);
  667. j:=1;
  668. while (j<i) and (s[j] in [#9,' ']) do
  669. inc(j);
  670. trimspace:=Copy(s,j,i-j+1);
  671. end;
  672. function trimspace(const s:AnsiString):AnsiString;
  673. {
  674. return s with all leading and ending spaces and tabs removed
  675. }
  676. var
  677. i,j : longint;
  678. begin
  679. i:=length(s);
  680. while (i>0) and (s[i] in [#9,' ']) do
  681. dec(i);
  682. j:=1;
  683. while (j<i) and (s[j] in [#9,' ']) do
  684. inc(j);
  685. trimspace:=Copy(s,j,i-j+1);
  686. end;
  687. function space (b : longint): string;
  688. var
  689. s: string;
  690. begin
  691. space[0] := chr(b);
  692. s[0] := chr(b);
  693. FillChar (S[1],b,' ');
  694. space:=s;
  695. end;
  696. function PadSpace(const s:string;len:longint):string;
  697. {
  698. return s with spaces add to the end
  699. }
  700. begin
  701. if length(s)<len then
  702. PadSpace:=s+Space(len-length(s))
  703. else
  704. PadSpace:=s;
  705. end;
  706. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  707. {
  708. return s with spaces add to the end
  709. }
  710. begin
  711. if length(s)<len then
  712. PadSpace:=s+Space(len-length(s))
  713. else
  714. PadSpace:=s;
  715. end;
  716. function GetToken(var s:string;endchar:char):string;
  717. var
  718. i : longint;
  719. quote : char;
  720. begin
  721. GetToken:='';
  722. s:=TrimSpace(s);
  723. if (length(s)>0) and
  724. (s[1] in ['''','"']) then
  725. begin
  726. quote:=s[1];
  727. i:=1;
  728. while (i<length(s)) do
  729. begin
  730. inc(i);
  731. if s[i]=quote then
  732. begin
  733. { Remove double quote }
  734. if (i<length(s)) and
  735. (s[i+1]=quote) then
  736. begin
  737. Delete(s,i,1);
  738. inc(i);
  739. end
  740. else
  741. begin
  742. GetToken:=Copy(s,2,i-2);
  743. Delete(s,1,i);
  744. exit;
  745. end;
  746. end;
  747. end;
  748. GetToken:=s;
  749. s:='';
  750. end
  751. else
  752. begin
  753. i:=pos(EndChar,s);
  754. if i=0 then
  755. begin
  756. GetToken:=s;
  757. s:='';
  758. exit;
  759. end
  760. else
  761. begin
  762. GetToken:=Copy(s,1,i-1);
  763. Delete(s,1,i);
  764. exit;
  765. end;
  766. end;
  767. end;
  768. function GetToken(var s:ansistring;endchar:char):ansistring;
  769. var
  770. i : longint;
  771. quote : char;
  772. begin
  773. GetToken:='';
  774. s:=TrimSpace(s);
  775. if (length(s)>0) and
  776. (s[1] in ['''','"']) then
  777. begin
  778. quote:=s[1];
  779. i:=1;
  780. while (i<length(s)) do
  781. begin
  782. inc(i);
  783. if s[i]=quote then
  784. begin
  785. { Remove double quote }
  786. if (i<length(s)) and
  787. (s[i+1]=quote) then
  788. begin
  789. Delete(s,i,1);
  790. inc(i);
  791. end
  792. else
  793. begin
  794. GetToken:=Copy(s,2,i-2);
  795. Delete(s,1,i);
  796. exit;
  797. end;
  798. end;
  799. end;
  800. GetToken:=s;
  801. s:='';
  802. end
  803. else
  804. begin
  805. i:=pos(EndChar,s);
  806. if i=0 then
  807. begin
  808. GetToken:=s;
  809. s:='';
  810. exit;
  811. end
  812. else
  813. begin
  814. GetToken:=Copy(s,1,i-1);
  815. Delete(s,1,i);
  816. exit;
  817. end;
  818. end;
  819. end;
  820. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  821. begin
  822. str(e,result);
  823. end;
  824. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  825. {
  826. return string of value i
  827. }
  828. begin
  829. str(i,result);
  830. end;
  831. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  832. {
  833. return string of value i
  834. }
  835. begin
  836. str(i,result);
  837. end;
  838. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  839. {
  840. return string of value i
  841. }
  842. begin
  843. str(i,result);
  844. end;
  845. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  846. {
  847. return string of value i, but always include a + when i>=0
  848. }
  849. begin
  850. str(i,result);
  851. if i>=0 then
  852. result:='+'+result;
  853. end;
  854. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  855. {
  856. is string a correct number ?
  857. }
  858. var
  859. w : integer;
  860. l : longint;
  861. begin
  862. val(s,l,w);
  863. // remove warning
  864. l:=l;
  865. is_number:=(w=0);
  866. end;
  867. function ispowerof2(value : int64;out power : longint) : boolean;
  868. {
  869. return if value is a power of 2. And if correct return the power
  870. }
  871. begin
  872. if (value <= 0) or (value and (value - 1) <> 0) then
  873. exit(false);
  874. power:=BsfQWord(value);
  875. result:=true;
  876. end;
  877. function ispowerof2(const value: Tconstexprint; out power: longint): boolean;
  878. begin
  879. if value.signed or
  880. (value.uvalue<=high(int64)) then
  881. result:=ispowerof2(value.svalue,power)
  882. else if not value.signed and
  883. (value.svalue=low(int64)) then
  884. begin
  885. result:=true;
  886. power:=63;
  887. end
  888. else
  889. result:=false;
  890. end;
  891. function isabspowerof2(const value : Tconstexprint;out power : longint) : boolean;
  892. begin
  893. if ispowerof2(value,power) then
  894. result:=true
  895. else if value.signed and (value.svalue<0) and (value.svalue<>low(int64)) and ispowerof2(-value.svalue,power) then
  896. result:=true
  897. else
  898. result:=false;
  899. end;
  900. function nextpowerof2(value : qword; out power: longint) : qword;
  901. begin
  902. power:=-1;
  903. result:=0;
  904. if (value=0) or (value>qword($8000000000000000)) then
  905. exit;
  906. power:=BsrQWord(value);
  907. result:=qword(1) shl power;
  908. if (value and (value-1))<>0 then
  909. begin
  910. inc(power);
  911. result:=result shl 1;
  912. end;
  913. end;
  914. function backspace_quote(const s:string;const qchars:Tcharset):string;
  915. var i:byte;
  916. begin
  917. backspace_quote:='';
  918. for i:=1 to length(s) do
  919. begin
  920. if (s[i]=#10) and (#10 in qchars) then
  921. backspace_quote:=backspace_quote+'\n'
  922. else if (s[i]=#13) and (#13 in qchars) then
  923. backspace_quote:=backspace_quote+'\r'
  924. else
  925. begin
  926. if s[i] in qchars then
  927. backspace_quote:=backspace_quote+'\';
  928. backspace_quote:=backspace_quote+s[i];
  929. end;
  930. end;
  931. end;
  932. function octal_quote(const s:string;const qchars:Tcharset):string;
  933. var i:byte;
  934. begin
  935. octal_quote:='';
  936. for i:=1 to length(s) do
  937. begin
  938. if s[i] in qchars then
  939. begin
  940. if ord(s[i])<64 then
  941. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  942. else
  943. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  944. end
  945. else
  946. octal_quote:=octal_quote+s[i];
  947. end;
  948. end;
  949. function DePascalQuote(var s: ansistring): Boolean;
  950. var
  951. destPos, sourcePos, len: Integer;
  952. t: string;
  953. ch: Char;
  954. begin
  955. t:='';
  956. DePascalQuote:= false;
  957. len:= length(s);
  958. if (len >= 1) and (s[1] = '''') then
  959. begin
  960. {Remove quotes, exchange '' against ' }
  961. destPos := 0;
  962. sourcepos:=1;
  963. while (sourcepos<len) do
  964. begin
  965. inc(sourcePos);
  966. ch := s[sourcePos];
  967. if ch = '''' then
  968. begin
  969. inc(sourcePos);
  970. if (sourcePos <= len) and (s[sourcePos] = '''') then
  971. {Add the quote as part of string}
  972. else
  973. begin
  974. SetLength(t, destPos);
  975. s:= t;
  976. Exit(true);
  977. end;
  978. end;
  979. inc(destPos);
  980. t[destPos] := ch;
  981. end;
  982. end;
  983. end;
  984. function pchar2pshortstring(p : pchar) : pshortstring;
  985. var
  986. w,i : longint;
  987. begin
  988. w:=strlen(p);
  989. for i:=w-1 downto 0 do
  990. p[i+1]:=p[i];
  991. p[0]:=chr(w);
  992. pchar2pshortstring:=pshortstring(p);
  993. end;
  994. function pshortstring2pchar(p : pshortstring) : pchar;
  995. var
  996. w,i : longint;
  997. begin
  998. w:=length(p^);
  999. for i:=1 to w do
  1000. p^[i-1]:=p^[i];
  1001. p^[w]:=#0;
  1002. pshortstring2pchar:=pchar(p);
  1003. end;
  1004. function ansistring2pchar(const a: ansistring) : pchar;
  1005. var
  1006. len: ptrint;
  1007. begin
  1008. len:=length(a);
  1009. getmem(result,len+1);
  1010. if (len<>0) then
  1011. move(a[1],result[0],len);
  1012. result[len]:=#0;
  1013. end;
  1014. function lowercase(c : char) : char;
  1015. begin
  1016. case c of
  1017. #65..#90 : c := chr(ord (c) + 32);
  1018. #154 : c:=#129; { german }
  1019. #142 : c:=#132; { german }
  1020. #153 : c:=#148; { german }
  1021. #144 : c:=#130; { french }
  1022. #128 : c:=#135; { french }
  1023. #143 : c:=#134; { swedish/norge (?) }
  1024. #165 : c:=#164; { spanish }
  1025. #228 : c:=#229; { greek }
  1026. #226 : c:=#231; { greek }
  1027. #232 : c:=#227; { greek }
  1028. end;
  1029. lowercase := c;
  1030. end;
  1031. function strpnew(const s : string) : pchar;
  1032. var
  1033. p : pchar;
  1034. begin
  1035. getmem(p,length(s)+1);
  1036. move(s[1],p^,length(s));
  1037. p[length(s)]:=#0;
  1038. result:=p;
  1039. end;
  1040. function strpnew(const s: ansistring): pchar;
  1041. var
  1042. p : pchar;
  1043. begin
  1044. getmem(p,length(s)+1);
  1045. move(s[1],p^,length(s)+1);
  1046. result:=p;
  1047. end;
  1048. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  1049. begin
  1050. if assigned(p) then
  1051. begin
  1052. freemem(p);
  1053. p:=nil;
  1054. end;
  1055. end;
  1056. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1057. begin
  1058. getmem(result,length(s)+1);
  1059. result^:=s;
  1060. end;
  1061. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1062. begin
  1063. getmem(result,length(s)+1);
  1064. result^:=s;
  1065. end;
  1066. function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
  1067. var
  1068. i : integer;
  1069. begin
  1070. result:=0;
  1071. for i:=1 to length(s) do
  1072. if s[i] in cs then
  1073. begin
  1074. result:=i;
  1075. exit;
  1076. end;
  1077. end;
  1078. function CompareStr(const S1, S2: string): Integer;
  1079. var
  1080. count, count1, count2: integer;
  1081. begin
  1082. result := 0;
  1083. Count1 := Length(S1);
  1084. Count2 := Length(S2);
  1085. if Count1>Count2 then
  1086. Count:=Count2
  1087. else
  1088. Count:=Count1;
  1089. result := CompareChar(S1[1],S2[1], Count);
  1090. if result=0 then
  1091. result:=Count1-Count2;
  1092. end;
  1093. function CompareText(S1, S2: string): integer;
  1094. begin
  1095. UpperVar(S1);
  1096. UpperVar(S2);
  1097. Result:=CompareStr(S1,S2);
  1098. end;
  1099. function CompareVersionStrings(s1,s2: string): longint;
  1100. var
  1101. start1, start2,
  1102. i1, i2,
  1103. num1,num2,
  1104. res,
  1105. err : longint;
  1106. begin
  1107. i1:=1;
  1108. i2:=1;
  1109. repeat
  1110. start1:=i1;
  1111. start2:=i2;
  1112. while (i1<=length(s1)) and
  1113. (s1[i1] in ['0'..'9']) do
  1114. inc(i1);
  1115. while (i2<=length(s2)) and
  1116. (s2[i2] in ['0'..'9']) do
  1117. inc(i2);
  1118. { one of the strings misses digits -> other is the largest version }
  1119. if i1=start1 then
  1120. if i2=start2 then
  1121. exit(0)
  1122. else
  1123. exit(-1)
  1124. else if i2=start2 then
  1125. exit(1);
  1126. { get version number part }
  1127. val(copy(s1,start1,i1-start1),num1,err);
  1128. val(copy(s2,start2,i2-start2),num2,err);
  1129. { different -> done }
  1130. res:=num1-num2;
  1131. if res<>0 then
  1132. exit(res);
  1133. { if one of the two is at the end while the other isn't, add a '.0' }
  1134. if (i1>length(s1)) and
  1135. (i2<=length(s2)) then
  1136. s1:=s1+'.0';
  1137. if (i2>length(s2)) and
  1138. (i1<=length(s1)) then
  1139. s2:=s2+'.0';
  1140. { compare non-numerical characters normally }
  1141. while (i1<=length(s1)) and
  1142. not(s1[i1] in ['0'..'9']) and
  1143. (i2<=length(s2)) and
  1144. not(s2[i2] in ['0'..'9']) do
  1145. begin
  1146. res:=ord(s1[i1])-ord(s2[i2]);
  1147. if res<>0 then
  1148. exit(res);
  1149. inc(i1);
  1150. inc(i2);
  1151. end;
  1152. { both should be digits again now, otherwise pick the one with the
  1153. digits as the largest (it more likely means that the input was
  1154. ill-formatted though) }
  1155. if (i1<=length(s1)) and
  1156. not(s1[i1] in ['0'..'9']) then
  1157. exit(-1);
  1158. if (i2<=length(s2)) and
  1159. not(s2[i2] in ['0'..'9']) then
  1160. exit(1);
  1161. until false;
  1162. end;
  1163. {*****************************************************************************
  1164. Ansistring (PChar+Length)
  1165. *****************************************************************************}
  1166. procedure ansistringdispose(var p : pchar;length : longint);
  1167. begin
  1168. if assigned(p) then
  1169. begin
  1170. freemem(p);
  1171. p:=nil;
  1172. end;
  1173. end;
  1174. { enable ansistring comparison }
  1175. { 0 means equal }
  1176. { 1 means p1 > p2 }
  1177. { -1 means p1 < p2 }
  1178. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  1179. var
  1180. i,j : longint;
  1181. begin
  1182. compareansistrings:=0;
  1183. j:=min(length1,length2);
  1184. i:=0;
  1185. while (i<j) do
  1186. begin
  1187. if p1[i]>p2[i] then
  1188. begin
  1189. compareansistrings:=1;
  1190. exit;
  1191. end
  1192. else
  1193. if p1[i]<p2[i] then
  1194. begin
  1195. compareansistrings:=-1;
  1196. exit;
  1197. end;
  1198. inc(i);
  1199. end;
  1200. if length1>length2 then
  1201. compareansistrings:=1
  1202. else
  1203. if length1<length2 then
  1204. compareansistrings:=-1;
  1205. end;
  1206. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  1207. var
  1208. p : pchar;
  1209. begin
  1210. getmem(p,length1+length2+1);
  1211. move(p1[0],p[0],length1);
  1212. move(p2[0],p[length1],length2+1);
  1213. concatansistrings:=p;
  1214. end;
  1215. {*****************************************************************************
  1216. Ultra basic KISS Lzw (de)compressor
  1217. *****************************************************************************}
  1218. {This is an extremely basic implementation of the Lzw algorithm. It
  1219. compresses 7-bit ASCII strings into 8-bit compressed strings.
  1220. The Lzw dictionary is preinitialized with 0..127, therefore this
  1221. part of the dictionary does not need to be stored in the arrays.
  1222. The Lzw code size is allways 8 bit, so we do not need complex code
  1223. that can write partial bytes.}
  1224. function minilzw_encode(const s:string):string;
  1225. var t,u,i:byte;
  1226. c:char;
  1227. data:array[128..255] of char;
  1228. previous:array[128..255] of byte;
  1229. lzwptr:byte;
  1230. next_avail:set of 0..255;
  1231. label l1;
  1232. begin
  1233. minilzw_encode:='';
  1234. fillchar(data,sizeof(data),#0);
  1235. fillchar(previous,sizeof(previous),#0);
  1236. if s<>'' then
  1237. begin
  1238. lzwptr:=127;
  1239. t:=byte(s[1]);
  1240. i:=2;
  1241. u:=128;
  1242. next_avail:=[];
  1243. while i<=length(s) do
  1244. begin
  1245. c:=s[i];
  1246. if not(t in next_avail) or (u>lzwptr) then goto l1;
  1247. while (previous[u]<>t) or (data[u]<>c) do
  1248. begin
  1249. inc(u);
  1250. if u>lzwptr then goto l1;
  1251. end;
  1252. t:=u;
  1253. inc(i);
  1254. continue;
  1255. l1:
  1256. {It's a pity that we still need those awfull tricks
  1257. with this modern compiler. Without this performance
  1258. of the entire procedure drops about 3 times.}
  1259. inc(minilzw_encode[0]);
  1260. minilzw_encode[length(minilzw_encode)]:=char(t);
  1261. if lzwptr=255 then
  1262. begin
  1263. lzwptr:=127;
  1264. next_avail:=[];
  1265. end
  1266. else
  1267. begin
  1268. inc(lzwptr);
  1269. data[lzwptr]:=c;
  1270. previous[lzwptr]:=t;
  1271. include(next_avail,t);
  1272. end;
  1273. t:=byte(c);
  1274. u:=128;
  1275. inc(i);
  1276. end;
  1277. inc(minilzw_encode[0]);
  1278. minilzw_encode[length(minilzw_encode)]:=char(t);
  1279. end;
  1280. end;
  1281. function minilzw_decode(const s:string):string;
  1282. var oldc,newc,c:char;
  1283. i,j:byte;
  1284. data:array[128..255] of char;
  1285. previous:array[128..255] of byte;
  1286. lzwptr:byte;
  1287. t:string;
  1288. begin
  1289. minilzw_decode:='';
  1290. fillchar(data,sizeof(data),#0);
  1291. fillchar(previous,sizeof(previous),#0);
  1292. if s<>'' then
  1293. begin
  1294. lzwptr:=127;
  1295. oldc:=s[1];
  1296. c:=oldc;
  1297. i:=2;
  1298. minilzw_decode:=oldc;
  1299. while i<=length(s) do
  1300. begin
  1301. newc:=s[i];
  1302. if byte(newc)>lzwptr then
  1303. begin
  1304. t:=c;
  1305. c:=oldc;
  1306. end
  1307. else
  1308. begin
  1309. c:=newc;
  1310. t:='';
  1311. end;
  1312. while c>=#128 do
  1313. begin
  1314. inc(t[0]);
  1315. t[length(t)]:=data[byte(c)];
  1316. byte(c):=previous[byte(c)];
  1317. end;
  1318. inc(minilzw_decode[0]);
  1319. minilzw_decode[length(minilzw_decode)]:=c;
  1320. for j:=length(t) downto 1 do
  1321. begin
  1322. inc(minilzw_decode[0]);
  1323. minilzw_decode[length(minilzw_decode)]:=t[j];
  1324. end;
  1325. if lzwptr=255 then
  1326. lzwptr:=127
  1327. else
  1328. begin
  1329. inc(lzwptr);
  1330. previous[lzwptr]:=byte(oldc);
  1331. data[lzwptr]:=c;
  1332. end;
  1333. oldc:=newc;
  1334. inc(i);
  1335. end;
  1336. end;
  1337. end;
  1338. procedure defaulterror(i:longint);
  1339. begin
  1340. writeln('Internal error ',i);
  1341. runerror(255);
  1342. end;
  1343. Function Nextafter(x,y:double):double;
  1344. // Returns the double precision number closest to x in
  1345. // the direction toward y.
  1346. // Initial direct translation by Soeren Haastrup from
  1347. // www.netlib.org/fdlibm/s_nextafter.c according to
  1348. // ====================================================
  1349. // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1350. // Developed at SunSoft, a Sun Microsystems, Inc. business.
  1351. // Permission to use, copy, modify, and distribute this
  1352. // software is freely granted, provided that this notice
  1353. // is preserved.
  1354. // ====================================================
  1355. // and with all signaling policies preserved as is.
  1356. type
  1357. {$if defined(ENDIAN_LITTLE) and not defined(FPC_DOUBLE_HILO_SWAPPED)}
  1358. twoword=record
  1359. lo,hi:longword; // Little Endian split of a double.
  1360. end;
  1361. {$else}
  1362. twoword=record
  1363. hi,lo:longword; // Big Endian split of a double.
  1364. end;
  1365. {$endif}
  1366. var
  1367. hx,hy,ix,iy:longint;
  1368. lx,ly:longword;
  1369. Begin
  1370. hx:=twoword(x).hi; // high and low words of x and y
  1371. lx:=twoword(x).lo;
  1372. hy:=twoword(y).hi;
  1373. ly:=twoword(y).lo;
  1374. ix:=hx and $7fffffff; // absolute values
  1375. iy:=hy and $7fffffff;
  1376. // Case x=NAN or y=NAN
  1377. if ( (ix>=$7ff00000) and ((longword(ix-$7ff00000) or lx) <> 0) )
  1378. or ( (iy>=$7ff00000) and ((longword(iy-$7ff00000) OR ly) <> 0) )
  1379. then exit(x+y);
  1380. // Case x=y
  1381. if x=y then exit(x); // (implies Nextafter(0,-0) is 0 and not -0...)
  1382. // Case x=0
  1383. if (longword(ix) or lx)=0
  1384. then begin
  1385. twoword(x).hi:=hy and $80000000; // return +-minimalSubnormal
  1386. twoword(x).lo:=1;
  1387. y:=x*x; // set underflow flag (ignored in FPC as default)
  1388. if y=x
  1389. then exit(y)
  1390. else exit(x);
  1391. end;
  1392. // all other cases
  1393. if hx>=0 // x>0
  1394. then begin
  1395. if (hx>hy) or ( (hx=hy) and (lx>ly) ) // x>y , return x-ulp
  1396. then begin
  1397. if (lx=0) then hx:=hx-1;
  1398. lx:=lx-1;
  1399. end
  1400. else begin // x<y, return x+ulp
  1401. lx:=lx+1;
  1402. if lx=0 then hx:=hx+1;
  1403. end
  1404. end
  1405. else begin // x<0
  1406. if (hy>=0) or (hx>=hy) or ( (hx=hy) and (lx>ly)) // x<y, return x-ulp
  1407. then begin
  1408. if (lx=0) then hx:=hx-1;
  1409. lx:=lx-1;
  1410. end
  1411. else begin // x>y , return x+ulp
  1412. lx:=lx+1;
  1413. if lx=0 then hx:=hx+1;
  1414. end
  1415. end;
  1416. // finally check if overflow or underflow just happend
  1417. hy:=hx and $7ff00000;
  1418. if (hy>= $7ff00000) then exit(x+x); // overflow and signal
  1419. if (hy<$0010000) // underflow
  1420. then begin
  1421. y:=x*x; // raise underflow flag
  1422. if y<>x
  1423. then begin
  1424. twoword(y).hi:=hx;
  1425. twoword(y).lo:=lx;
  1426. exit(y);
  1427. end
  1428. end;
  1429. twoword(x).hi:=hx;
  1430. twoword(x).lo:=lx;
  1431. nextafter:=x;
  1432. end;
  1433. function LengthUleb128(a: qword) : byte;
  1434. begin
  1435. result:=0;
  1436. repeat
  1437. inc(result);
  1438. a := a shr 7;
  1439. until a=0;
  1440. end;
  1441. function LengthSleb128(a: int64) : byte;
  1442. begin
  1443. { '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.
  1444. 'shl 1' ensures storing the sign bit. }
  1445. result:=LengthUleb128(qword(a xor SarInt64(a,63)) shl 1);
  1446. end;
  1447. function EncodeUleb128(a: qword;out buf;len : byte) : byte;
  1448. var
  1449. b: byte;
  1450. pbuf : pbyte;
  1451. begin
  1452. result:=0;
  1453. pbuf:=@buf;
  1454. repeat
  1455. b := a and $7f;
  1456. a := a shr 7;
  1457. if a<>0 then
  1458. b := b or $80;
  1459. pbuf^:=b;
  1460. inc(pbuf);
  1461. inc(result);
  1462. until (a=0) and (result>=len);
  1463. end;
  1464. function EncodeSleb128(a: int64;out buf;len : byte) : byte;
  1465. var
  1466. b: byte;
  1467. more: boolean;
  1468. pbuf : pbyte;
  1469. begin
  1470. result:=0;
  1471. pbuf:=@buf;
  1472. repeat
  1473. b := a and $7f;
  1474. a := SarInt64(a, 7);
  1475. inc(result);
  1476. more:=(result<len) or (a<>-(b shr 6));
  1477. pbuf^:=b or byte(more) shl 7;
  1478. inc(pbuf);
  1479. until not more;
  1480. end;
  1481. initialization
  1482. internalerrorproc:=@defaulterror;
  1483. initupperlower;
  1484. end.