cutils.pas 40 KB

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