cutils.pas 40 KB

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