cutils.pas 37 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419
  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. begin
  707. if (value = 0) or (value and (value - 1) <> 0) then
  708. exit(false);
  709. power:=BsfQWord(value);
  710. result:=true;
  711. end;
  712. function nextpowerof2(value : int64; out power: longint) : int64;
  713. {
  714. returns the power of 2 >= value
  715. }
  716. var
  717. i : longint;
  718. begin
  719. result := 0;
  720. power := -1;
  721. if ((value <= 0) or
  722. (value >= $4000000000000000)) then
  723. exit;
  724. result := 1;
  725. for i:=0 to 63 do
  726. begin
  727. if result>=value then
  728. begin
  729. power := i;
  730. exit;
  731. end;
  732. result:=result shl 1;
  733. end;
  734. end;
  735. function backspace_quote(const s:string;const qchars:Tcharset):string;
  736. var i:byte;
  737. begin
  738. backspace_quote:='';
  739. for i:=1 to length(s) do
  740. begin
  741. if (s[i]=#10) and (#10 in qchars) then
  742. backspace_quote:=backspace_quote+'\n'
  743. else if (s[i]=#13) and (#13 in qchars) then
  744. backspace_quote:=backspace_quote+'\r'
  745. else
  746. begin
  747. if s[i] in qchars then
  748. backspace_quote:=backspace_quote+'\';
  749. backspace_quote:=backspace_quote+s[i];
  750. end;
  751. end;
  752. end;
  753. function octal_quote(const s:string;const qchars:Tcharset):string;
  754. var i:byte;
  755. begin
  756. octal_quote:='';
  757. for i:=1 to length(s) do
  758. begin
  759. if s[i] in qchars then
  760. begin
  761. if ord(s[i])<64 then
  762. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  763. else
  764. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  765. end
  766. else
  767. octal_quote:=octal_quote+s[i];
  768. end;
  769. end;
  770. function DePascalQuote(var s: ansistring): Boolean;
  771. var
  772. destPos, sourcePos, len: Integer;
  773. t: string;
  774. ch: Char;
  775. begin
  776. DePascalQuote:= false;
  777. len:= length(s);
  778. if (len >= 1) and (s[1] = '''') then
  779. begin
  780. {Remove quotes, exchange '' against ' }
  781. destPos := 0;
  782. sourcepos:=1;
  783. while (sourcepos<len) do
  784. begin
  785. inc(sourcePos);
  786. ch := s[sourcePos];
  787. if ch = '''' then
  788. begin
  789. inc(sourcePos);
  790. if (sourcePos <= len) and (s[sourcePos] = '''') then
  791. {Add the quote as part of string}
  792. else
  793. begin
  794. SetLength(t, destPos);
  795. s:= t;
  796. Exit(true);
  797. end;
  798. end;
  799. inc(destPos);
  800. t[destPos] := ch;
  801. end;
  802. end;
  803. end;
  804. function pchar2pshortstring(p : pchar) : pshortstring;
  805. var
  806. w,i : longint;
  807. begin
  808. w:=strlen(p);
  809. for i:=w-1 downto 0 do
  810. p[i+1]:=p[i];
  811. p[0]:=chr(w);
  812. pchar2pshortstring:=pshortstring(p);
  813. end;
  814. function pshortstring2pchar(p : pshortstring) : pchar;
  815. var
  816. w,i : longint;
  817. begin
  818. w:=length(p^);
  819. for i:=1 to w do
  820. p^[i-1]:=p^[i];
  821. p^[w]:=#0;
  822. pshortstring2pchar:=pchar(p);
  823. end;
  824. function ansistring2pchar(const a: ansistring) : pchar;
  825. var
  826. len: ptrint;
  827. begin
  828. len:=length(a);
  829. getmem(result,len+1);
  830. if (len<>0) then
  831. move(a[1],result[0],len);
  832. result[len]:=#0;
  833. end;
  834. function lowercase(c : char) : char;
  835. begin
  836. case c of
  837. #65..#90 : c := chr(ord (c) + 32);
  838. #154 : c:=#129; { german }
  839. #142 : c:=#132; { german }
  840. #153 : c:=#148; { german }
  841. #144 : c:=#130; { french }
  842. #128 : c:=#135; { french }
  843. #143 : c:=#134; { swedish/norge (?) }
  844. #165 : c:=#164; { spanish }
  845. #228 : c:=#229; { greek }
  846. #226 : c:=#231; { greek }
  847. #232 : c:=#227; { greek }
  848. end;
  849. lowercase := c;
  850. end;
  851. function strpnew(const s : string) : pchar;
  852. var
  853. p : pchar;
  854. begin
  855. getmem(p,length(s)+1);
  856. move(s[1],p^,length(s));
  857. p[length(s)]:=#0;
  858. result:=p;
  859. end;
  860. function strpnew(const s: ansistring): pchar;
  861. var
  862. p : pchar;
  863. begin
  864. getmem(p,length(s)+1);
  865. move(s[1],p^,length(s)+1);
  866. result:=p;
  867. end;
  868. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  869. begin
  870. if assigned(p) then
  871. begin
  872. freemem(p);
  873. p:=nil;
  874. end;
  875. end;
  876. function stringdup(const s : string) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  877. begin
  878. getmem(result,length(s)+1);
  879. result^:=s;
  880. end;
  881. function CompareStr(const S1, S2: string): Integer;
  882. var
  883. count, count1, count2: integer;
  884. begin
  885. result := 0;
  886. Count1 := Length(S1);
  887. Count2 := Length(S2);
  888. if Count1>Count2 then
  889. Count:=Count2
  890. else
  891. Count:=Count1;
  892. result := CompareChar(S1[1],S2[1], Count);
  893. if result=0 then
  894. result:=Count1-Count2;
  895. end;
  896. function CompareText(S1, S2: string): integer;
  897. begin
  898. UpperVar(S1);
  899. UpperVar(S2);
  900. Result:=CompareStr(S1,S2);
  901. end;
  902. function CompareVersionStrings(s1,s2: string): longint;
  903. var
  904. start1, start2,
  905. i1, i2,
  906. num1,num2,
  907. res,
  908. err : longint;
  909. begin
  910. i1:=1;
  911. i2:=1;
  912. repeat
  913. start1:=i1;
  914. start2:=i2;
  915. while (i1<=length(s1)) and
  916. (s1[i1] in ['0'..'9']) do
  917. inc(i1);
  918. while (i2<=length(s2)) and
  919. (s2[i2] in ['0'..'9']) do
  920. inc(i2);
  921. { one of the strings misses digits -> other is the largest version }
  922. if i1=start1 then
  923. if i2=start2 then
  924. exit(0)
  925. else
  926. exit(-1)
  927. else if i2=start2 then
  928. exit(1);
  929. { get version number part }
  930. val(copy(s1,start1,i1-start1),num1,err);
  931. val(copy(s2,start2,i2-start2),num2,err);
  932. { different -> done }
  933. res:=num1-num2;
  934. if res<>0 then
  935. exit(res);
  936. { if one of the two is at the end while the other isn't, add a '.0' }
  937. if (i1>length(s1)) and
  938. (i2<=length(s1)) then
  939. s1:=s1+'.0'
  940. else if i2>length(s2) then
  941. s2:=s2+'.0';
  942. { compare non-numerical characters normally }
  943. while (i1<=length(s1)) and
  944. not(s1[i1] in ['0'..'9']) and
  945. (i2<=length(s2)) and
  946. not(s2[i2] in ['0'..'9']) do
  947. begin
  948. res:=ord(s1[i1])-ord(s2[i2]);
  949. if res<>0 then
  950. exit(res);
  951. inc(i1);
  952. inc(i2);
  953. end;
  954. { both should be digits again now, otherwise pick the one with the
  955. digits as the largest (it more likely means that the input was
  956. ill-formatted though) }
  957. if (i1<=length(s1)) and
  958. not(s1[i1] in ['0'..'9']) then
  959. exit(-1);
  960. if (i2<=length(s2)) and
  961. not(s2[i2] in ['0'..'9']) then
  962. exit(1);
  963. until false;
  964. end;
  965. {*****************************************************************************
  966. Ansistring (PChar+Length)
  967. *****************************************************************************}
  968. procedure ansistringdispose(var p : pchar;length : longint);
  969. begin
  970. if assigned(p) then
  971. begin
  972. freemem(p);
  973. p:=nil;
  974. end;
  975. end;
  976. { enable ansistring comparison }
  977. { 0 means equal }
  978. { 1 means p1 > p2 }
  979. { -1 means p1 < p2 }
  980. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  981. var
  982. i,j : longint;
  983. begin
  984. compareansistrings:=0;
  985. j:=min(length1,length2);
  986. i:=0;
  987. while (i<j) do
  988. begin
  989. if p1[i]>p2[i] then
  990. begin
  991. compareansistrings:=1;
  992. exit;
  993. end
  994. else
  995. if p1[i]<p2[i] then
  996. begin
  997. compareansistrings:=-1;
  998. exit;
  999. end;
  1000. inc(i);
  1001. end;
  1002. if length1>length2 then
  1003. compareansistrings:=1
  1004. else
  1005. if length1<length2 then
  1006. compareansistrings:=-1;
  1007. end;
  1008. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  1009. var
  1010. p : pchar;
  1011. begin
  1012. getmem(p,length1+length2+1);
  1013. move(p1[0],p[0],length1);
  1014. move(p2[0],p[length1],length2+1);
  1015. concatansistrings:=p;
  1016. end;
  1017. {*****************************************************************************
  1018. Ultra basic KISS Lzw (de)compressor
  1019. *****************************************************************************}
  1020. {This is an extremely basic implementation of the Lzw algorithm. It
  1021. compresses 7-bit ASCII strings into 8-bit compressed strings.
  1022. The Lzw dictionary is preinitialized with 0..127, therefore this
  1023. part of the dictionary does not need to be stored in the arrays.
  1024. The Lzw code size is allways 8 bit, so we do not need complex code
  1025. that can write partial bytes.}
  1026. function minilzw_encode(const s:string):string;
  1027. var t,u,i:byte;
  1028. c:char;
  1029. data:array[128..255] of char;
  1030. previous:array[128..255] of byte;
  1031. lzwptr:byte;
  1032. next_avail:set of 0..255;
  1033. label l1;
  1034. begin
  1035. minilzw_encode:='';
  1036. fillchar(data,sizeof(data),#0);
  1037. fillchar(previous,sizeof(previous),#0);
  1038. if s<>'' then
  1039. begin
  1040. lzwptr:=127;
  1041. t:=byte(s[1]);
  1042. i:=2;
  1043. u:=128;
  1044. next_avail:=[];
  1045. while i<=length(s) do
  1046. begin
  1047. c:=s[i];
  1048. if not(t in next_avail) or (u>lzwptr) then goto l1;
  1049. while (previous[u]<>t) or (data[u]<>c) do
  1050. begin
  1051. inc(u);
  1052. if u>lzwptr then goto l1;
  1053. end;
  1054. t:=u;
  1055. inc(i);
  1056. continue;
  1057. l1:
  1058. {It's a pity that we still need those awfull tricks
  1059. with this modern compiler. Without this performance
  1060. of the entire procedure drops about 3 times.}
  1061. inc(minilzw_encode[0]);
  1062. minilzw_encode[length(minilzw_encode)]:=char(t);
  1063. if lzwptr=255 then
  1064. begin
  1065. lzwptr:=127;
  1066. next_avail:=[];
  1067. end
  1068. else
  1069. begin
  1070. inc(lzwptr);
  1071. data[lzwptr]:=c;
  1072. previous[lzwptr]:=t;
  1073. include(next_avail,t);
  1074. end;
  1075. t:=byte(c);
  1076. u:=128;
  1077. inc(i);
  1078. end;
  1079. inc(minilzw_encode[0]);
  1080. minilzw_encode[length(minilzw_encode)]:=char(t);
  1081. end;
  1082. end;
  1083. function minilzw_decode(const s:string):string;
  1084. var oldc,newc,c:char;
  1085. i,j:byte;
  1086. data:array[128..255] of char;
  1087. previous:array[128..255] of byte;
  1088. lzwptr:byte;
  1089. t:string;
  1090. begin
  1091. minilzw_decode:='';
  1092. fillchar(data,sizeof(data),#0);
  1093. fillchar(previous,sizeof(previous),#0);
  1094. if s<>'' then
  1095. begin
  1096. lzwptr:=127;
  1097. oldc:=s[1];
  1098. c:=oldc;
  1099. i:=2;
  1100. minilzw_decode:=oldc;
  1101. while i<=length(s) do
  1102. begin
  1103. newc:=s[i];
  1104. if byte(newc)>lzwptr then
  1105. begin
  1106. t:=c;
  1107. c:=oldc;
  1108. end
  1109. else
  1110. begin
  1111. c:=newc;
  1112. t:='';
  1113. end;
  1114. while c>=#128 do
  1115. begin
  1116. inc(t[0]);
  1117. t[length(t)]:=data[byte(c)];
  1118. byte(c):=previous[byte(c)];
  1119. end;
  1120. inc(minilzw_decode[0]);
  1121. minilzw_decode[length(minilzw_decode)]:=c;
  1122. for j:=length(t) downto 1 do
  1123. begin
  1124. inc(minilzw_decode[0]);
  1125. minilzw_decode[length(minilzw_decode)]:=t[j];
  1126. end;
  1127. if lzwptr=255 then
  1128. lzwptr:=127
  1129. else
  1130. begin
  1131. inc(lzwptr);
  1132. previous[lzwptr]:=byte(oldc);
  1133. data[lzwptr]:=c;
  1134. end;
  1135. oldc:=newc;
  1136. inc(i);
  1137. end;
  1138. end;
  1139. end;
  1140. procedure defaulterror(i:longint);
  1141. begin
  1142. writeln('Internal error ',i);
  1143. runerror(255);
  1144. end;
  1145. Function Nextafter(x,y:double):double;
  1146. // Returns the double precision number closest to x in
  1147. // the direction toward y.
  1148. // Initial direct translation by Soeren Haastrup from
  1149. // www.netlib.org/fdlibm/s_nextafter.c according to
  1150. // ====================================================
  1151. // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1152. // Developed at SunSoft, a Sun Microsystems, Inc. business.
  1153. // Permission to use, copy, modify, and distribute this
  1154. // software is freely granted, provided that this notice
  1155. // is preserved.
  1156. // ====================================================
  1157. // and with all signaling policies preserved as is.
  1158. type
  1159. {$if defined(ENDIAN_LITTLE) and not defined(FPC_DOUBLE_HILO_SWAPPED)}
  1160. twoword=record
  1161. lo,hi:longword; // Little Endian split of a double.
  1162. end;
  1163. {$else}
  1164. twoword=record
  1165. hi,lo:longword; // Big Endian split of a double.
  1166. end;
  1167. {$endif}
  1168. var
  1169. hx,hy,ix,iy:longint;
  1170. lx,ly:longword;
  1171. Begin
  1172. hx:=twoword(x).hi; // high and low words of x and y
  1173. lx:=twoword(x).lo;
  1174. hy:=twoword(y).hi;
  1175. ly:=twoword(y).lo;
  1176. ix:=hx and $7fffffff; // absolute values
  1177. iy:=hy and $7fffffff;
  1178. // Case x=NAN or y=NAN
  1179. if ( (ix>=$7ff00000) and ((longword(ix-$7ff00000) or lx) <> 0) )
  1180. or ( (iy>=$7ff00000) and ((longword(iy-$7ff00000) OR ly) <> 0) )
  1181. then exit(x+y);
  1182. // Case x=y
  1183. if x=y then exit(x); // (implies Nextafter(0,-0) is 0 and not -0...)
  1184. // Case x=0
  1185. if (longword(ix) or lx)=0
  1186. then begin
  1187. twoword(x).hi:=hy and $80000000; // return +-minimalSubnormal
  1188. twoword(x).lo:=1;
  1189. y:=x*x; // set underflow flag (ignored in FPC as default)
  1190. if y=x
  1191. then exit(y)
  1192. else exit(x);
  1193. end;
  1194. // all other cases
  1195. if hx>=0 // x>0
  1196. then begin
  1197. if (hx>hy) or ( (hx=hy) and (lx>ly) ) // x>y , return x-ulp
  1198. then begin
  1199. if (lx=0) then hx:=hx-1;
  1200. lx:=lx-1;
  1201. end
  1202. else begin // x<y, return x+ulp
  1203. lx:=lx+1;
  1204. if lx=0 then hx:=hx+1;
  1205. end
  1206. end
  1207. else begin // x<0
  1208. if (hy>=0) or (hx>=hy) or ( (hx=hy) and (lx>ly)) // x<y, return x-ulp
  1209. then begin
  1210. if (lx=0) then hx:=hx-1;
  1211. lx:=lx-1;
  1212. end
  1213. else begin // x>y , return x+ulp
  1214. lx:=lx+1;
  1215. if lx=0 then hx:=hx+1;
  1216. end
  1217. end;
  1218. // finally check if overflow or underflow just happend
  1219. hy:=hx and $7ff00000;
  1220. if (hy>= $7ff00000) then exit(x+x); // overflow and signal
  1221. if (hy<$0010000) // underflow
  1222. then begin
  1223. y:=x*x; // raise underflow flag
  1224. if y<>x
  1225. then begin
  1226. twoword(y).hi:=hx;
  1227. twoword(y).lo:=lx;
  1228. exit(y);
  1229. end
  1230. end;
  1231. twoword(x).hi:=hx;
  1232. twoword(x).lo:=lx;
  1233. nextafter:=x;
  1234. end;
  1235. initialization
  1236. internalerrorproc:=@defaulterror;
  1237. initupperlower;
  1238. end.