cutils.pas 33 KB

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