cutils.pas 39 KB

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