cutils.pas 38 KB

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