cutils.pas 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047
  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. pstring = ^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. {# Return value @var(i) aligned on @var(a) boundary }
  41. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  42. function used_align(varalign,minalign,maxalign:shortint):shortint;
  43. function size_2_align(len : longint) : shortint;
  44. procedure Replace(var s:string;s1:string;const s2:string);
  45. procedure Replace(var s:AnsiString;s1:string;const s2:string);
  46. procedure ReplaceCase(var s:string;const s1,s2:string);
  47. function upper(const s : string) : string;
  48. function lower(const s : string) : string;
  49. function trimbspace(const s:string):string;
  50. function trimspace(const s:string):string;
  51. function space (b : longint): string;
  52. function PadSpace(const s:string;len:longint):string;
  53. function GetToken(var s:string;endchar:char):string;
  54. procedure uppervar(var s : string);
  55. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  56. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  57. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  58. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  59. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  60. function DStr(l:longint):string;
  61. {# Returns true if the string s is a number }
  62. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  63. {# Returns true if value is a power of 2, the actual
  64. exponent value is returned in power.
  65. }
  66. function ispowerof2(value : int64;out power : longint) : boolean;
  67. function backspace_quote(const s:string;const qchars:Tcharset):string;
  68. function octal_quote(const s:string;const qchars:Tcharset):string;
  69. function maybequoted(const s:string):string;
  70. {# If the string is quoted, in accordance with pascal, it is
  71. dequoted and returned in s, and the function returns true.
  72. If it is not quoted, or if the quoting is bad, s is not touched,
  73. and false is returned.
  74. }
  75. function DePascalQuote(var s: string): Boolean;
  76. function CompareText(S1, S2: string): longint;
  77. { releases the string p and assignes nil to p }
  78. { if p=nil then freemem isn't called }
  79. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  80. { allocates mem for a copy of s, copies s to this mem and returns }
  81. { a pointer to this mem }
  82. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  83. {# Allocates memory for the string @var(s) and copies s as zero
  84. terminated string to that allocated memory and returns a pointer
  85. to that mem
  86. }
  87. function strpnew(const s : string) : pchar;
  88. procedure strdispose(var p : pchar);
  89. {# makes the character @var(c) lowercase, with spanish, french and german
  90. character set
  91. }
  92. function lowercase(c : char) : char;
  93. { makes zero terminated string to a pascal string }
  94. { the data in p is modified and p is returned }
  95. function pchar2pstring(p : pchar) : pstring;
  96. { ambivalent to pchar2pstring }
  97. function pstring2pchar(p : pstring) : pchar;
  98. { Speed/Hash value }
  99. Function GetSpeedValue(Const s:String):cardinal;
  100. { Ansistring (pchar+length) support }
  101. procedure ansistringdispose(var p : pchar;length : longint);
  102. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  103. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  104. {Lzw encode/decode to compress strings -> save memory.}
  105. function minilzw_encode(const s:string):string;
  106. function minilzw_decode(const s:string):string;
  107. implementation
  108. uses
  109. strings
  110. ;
  111. var
  112. uppertbl,
  113. lowertbl : array[char] of char;
  114. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  115. {
  116. return the minimal of a and b
  117. }
  118. begin
  119. if a<=b then
  120. min:=a
  121. else
  122. min:=b;
  123. end;
  124. function min(a,b : int64) : int64;{$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 max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  135. {
  136. return the maximum of a and b
  137. }
  138. begin
  139. if a>=b then
  140. max:=a
  141. else
  142. max:=b;
  143. end;
  144. function max(a,b : int64) : int64;{$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 SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  155. var
  156. y : word;
  157. z : word;
  158. Begin
  159. y := x shr 16;
  160. y := word(longint(y) shl 8) or (y shr 8);
  161. z := x and $FFFF;
  162. z := word(longint(z) shl 8) or (z shr 8);
  163. SwapLong := (longint(z) shl 16) or longint(y);
  164. End;
  165. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  166. Begin
  167. result:=swaplong(longint(hi(x)));
  168. result:=result or (swaplong(longint(lo(x))) shl 32);
  169. End;
  170. Function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
  171. var
  172. z : byte;
  173. Begin
  174. z := x shr 8;
  175. x := x and $ff;
  176. x := (x shl 8);
  177. SwapWord := x or z;
  178. End;
  179. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  180. {
  181. return value <i> aligned <a> boundary
  182. }
  183. begin
  184. { for 0 and 1 no aligning is needed }
  185. if a<=1 then
  186. result:=i
  187. else
  188. begin
  189. if i<0 then
  190. result:=((i-a+1) div a) * a
  191. else
  192. result:=((i+a-1) div a) * a;
  193. end;
  194. end;
  195. function size_2_align(len : longint) : shortint;
  196. begin
  197. if len>16 then
  198. size_2_align:=32
  199. else if len>8 then
  200. size_2_align:=16
  201. else if len>4 then
  202. size_2_align:=8
  203. else if len>2 then
  204. size_2_align:=4
  205. else if len>1 then
  206. size_2_align:=2
  207. else
  208. size_2_align:=1;
  209. end;
  210. function used_align(varalign,minalign,maxalign:shortint):shortint;
  211. begin
  212. { varalign : minimum alignment required for the variable
  213. minalign : Minimum alignment of this structure, 0 = undefined
  214. maxalign : Maximum alignment of this structure, 0 = undefined }
  215. if (minalign>0) and
  216. (varalign<minalign) then
  217. used_align:=minalign
  218. else
  219. begin
  220. if (maxalign>0) and
  221. (varalign>maxalign) then
  222. used_align:=maxalign
  223. else
  224. used_align:=varalign;
  225. end;
  226. end;
  227. procedure Replace(var s:string;s1:string;const s2:string);
  228. var
  229. last,
  230. i : longint;
  231. begin
  232. s1:=upper(s1);
  233. last:=0;
  234. repeat
  235. i:=pos(s1,upper(s));
  236. if i=last then
  237. i:=0;
  238. if (i>0) then
  239. begin
  240. Delete(s,i,length(s1));
  241. Insert(s2,s,i);
  242. last:=i;
  243. end;
  244. until (i=0);
  245. end;
  246. procedure Replace(var s:AnsiString;s1:string;const s2:string);
  247. var
  248. last,
  249. i : longint;
  250. begin
  251. s1:=upper(s1);
  252. last:=0;
  253. repeat
  254. i:=pos(s1,upper(s));
  255. if i=last then
  256. i:=0;
  257. if (i>0) then
  258. begin
  259. Delete(s,i,length(s1));
  260. Insert(s2,s,i);
  261. last:=i;
  262. end;
  263. until (i=0);
  264. end;
  265. procedure ReplaceCase(var s:string;const s1,s2:string);
  266. var
  267. last,
  268. i : longint;
  269. begin
  270. last:=0;
  271. repeat
  272. i:=pos(s1,s);
  273. if i=last then
  274. i:=0;
  275. if (i>0) then
  276. begin
  277. Delete(s,i,length(s1));
  278. Insert(s2,s,i);
  279. last:=i;
  280. end;
  281. until (i=0);
  282. end;
  283. function upper(const s : string) : string;
  284. {
  285. return uppercased string of s
  286. }
  287. var
  288. i : longint;
  289. begin
  290. for i:=1 to length(s) do
  291. upper[i]:=uppertbl[s[i]];
  292. upper[0]:=s[0];
  293. end;
  294. function lower(const s : string) : string;
  295. {
  296. return lowercased string of s
  297. }
  298. var
  299. i : longint;
  300. begin
  301. for i:=1 to length(s) do
  302. lower[i]:=lowertbl[s[i]];
  303. lower[0]:=s[0];
  304. end;
  305. procedure uppervar(var s : string);
  306. {
  307. uppercase string s
  308. }
  309. var
  310. i : longint;
  311. begin
  312. for i:=1 to length(s) do
  313. s[i]:=uppertbl[s[i]];
  314. end;
  315. procedure initupperlower;
  316. var
  317. c : char;
  318. begin
  319. for c:=#0 to #255 do
  320. begin
  321. lowertbl[c]:=c;
  322. uppertbl[c]:=c;
  323. case c of
  324. 'A'..'Z' :
  325. lowertbl[c]:=char(byte(c)+32);
  326. 'a'..'z' :
  327. uppertbl[c]:=char(byte(c)-32);
  328. end;
  329. end;
  330. end;
  331. function DStr(l:longint):string;
  332. var
  333. TmpStr : string[32];
  334. i : longint;
  335. begin
  336. Str(l,TmpStr);
  337. i:=Length(TmpStr);
  338. while (i>3) do
  339. begin
  340. dec(i,3);
  341. if TmpStr[i]<>'-' then
  342. insert('.',TmpStr,i+1);
  343. end;
  344. DStr:=TmpStr;
  345. end;
  346. function trimbspace(const s:string):string;
  347. {
  348. return s with all leading spaces and tabs removed
  349. }
  350. var
  351. i,j : longint;
  352. begin
  353. j:=1;
  354. i:=length(s);
  355. while (j<i) and (s[j] in [#9,' ']) do
  356. inc(j);
  357. trimbspace:=Copy(s,j,i-j+1);
  358. end;
  359. function trimspace(const s:string):string;
  360. {
  361. return s with all leading and ending spaces and tabs removed
  362. }
  363. var
  364. i,j : longint;
  365. begin
  366. i:=length(s);
  367. while (i>0) and (s[i] in [#9,' ']) do
  368. dec(i);
  369. j:=1;
  370. while (j<i) and (s[j] in [#9,' ']) do
  371. inc(j);
  372. trimspace:=Copy(s,j,i-j+1);
  373. end;
  374. function space (b : longint): string;
  375. var
  376. s: string;
  377. begin
  378. space[0] := chr(b);
  379. s[0] := chr(b);
  380. FillChar (S[1],b,' ');
  381. space:=s;
  382. end;
  383. function PadSpace(const s:string;len:longint):string;
  384. {
  385. return s with spaces add to the end
  386. }
  387. begin
  388. if length(s)<len then
  389. PadSpace:=s+Space(len-length(s))
  390. else
  391. PadSpace:=s;
  392. end;
  393. function GetToken(var s:string;endchar:char):string;
  394. var
  395. i : longint;
  396. begin
  397. GetToken:='';
  398. s:=TrimSpace(s);
  399. if (length(s)>0) and
  400. (s[1]='''') then
  401. begin
  402. i:=1;
  403. while (i<length(s)) do
  404. begin
  405. inc(i);
  406. if s[i]='''' then
  407. begin
  408. { Remove double quote }
  409. if (i<length(s)) and
  410. (s[i+1]='''') then
  411. begin
  412. Delete(s,i,1);
  413. inc(i);
  414. end
  415. else
  416. begin
  417. GetToken:=Copy(s,2,i-2);
  418. Delete(s,1,i);
  419. exit;
  420. end;
  421. end;
  422. end;
  423. GetToken:=s;
  424. s:='';
  425. end
  426. else
  427. begin
  428. i:=pos(EndChar,s);
  429. if i=0 then
  430. begin
  431. GetToken:=s;
  432. s:='';
  433. exit;
  434. end
  435. else
  436. begin
  437. GetToken:=Copy(s,1,i-1);
  438. Delete(s,1,i);
  439. exit;
  440. end;
  441. end;
  442. end;
  443. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  444. begin
  445. str(e,result);
  446. end;
  447. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  448. {
  449. return string of value i
  450. }
  451. begin
  452. str(i,result);
  453. end;
  454. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  455. {
  456. return string of value i
  457. }
  458. begin
  459. str(i,result);
  460. end;
  461. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  462. {
  463. return string of value i
  464. }
  465. begin
  466. str(i,result);
  467. end;
  468. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  469. {
  470. return string of value i, but always include a + when i>=0
  471. }
  472. begin
  473. str(i,result);
  474. if i>=0 then
  475. result:='+'+result;
  476. end;
  477. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  478. {
  479. is string a correct number ?
  480. }
  481. var
  482. w : integer;
  483. l : longint;
  484. begin
  485. val(s,l,w);
  486. is_number:=(w=0);
  487. end;
  488. function ispowerof2(value : int64;out power : longint) : boolean;
  489. {
  490. return if value is a power of 2. And if correct return the power
  491. }
  492. var
  493. hl : int64;
  494. i : longint;
  495. begin
  496. if value and (value - 1) <> 0 then
  497. begin
  498. ispowerof2 := false;
  499. exit
  500. end;
  501. hl:=1;
  502. ispowerof2:=true;
  503. for i:=0 to 63 do
  504. begin
  505. if hl=value then
  506. begin
  507. power:=i;
  508. exit;
  509. end;
  510. hl:=hl shl 1;
  511. end;
  512. ispowerof2:=false;
  513. end;
  514. function backspace_quote(const s:string;const qchars:Tcharset):string;
  515. var i:byte;
  516. begin
  517. backspace_quote:='';
  518. for i:=1 to length(s) do
  519. begin
  520. if (s[i]=#10) and (#10 in qchars) then
  521. backspace_quote:=backspace_quote+'\n'
  522. else if (s[i]=#13) and (#13 in qchars) then
  523. backspace_quote:=backspace_quote+'\r'
  524. else
  525. begin
  526. if s[i] in qchars then
  527. backspace_quote:=backspace_quote+'\';
  528. backspace_quote:=backspace_quote+s[i];
  529. end;
  530. end;
  531. end;
  532. function octal_quote(const s:string;const qchars:Tcharset):string;
  533. var i:byte;
  534. begin
  535. octal_quote:='';
  536. for i:=1 to length(s) do
  537. begin
  538. if s[i] in qchars then
  539. begin
  540. if ord(s[i])<64 then
  541. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  542. else
  543. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  544. end
  545. else
  546. octal_quote:=octal_quote+s[i];
  547. end;
  548. end;
  549. function maybequoted(const s:string):string;
  550. var
  551. s1 : string;
  552. i : integer;
  553. quoted : boolean;
  554. begin
  555. quoted:=false;
  556. s1:='"';
  557. for i:=1 to length(s) do
  558. begin
  559. case s[i] of
  560. '"' :
  561. begin
  562. quoted:=true;
  563. s1:=s1+'\"';
  564. end;
  565. ' ',
  566. #128..#255 :
  567. begin
  568. quoted:=true;
  569. s1:=s1+s[i];
  570. end;
  571. else
  572. s1:=s1+s[i];
  573. end;
  574. end;
  575. if quoted then
  576. maybequoted:=s1+'"'
  577. else
  578. maybequoted:=s;
  579. end;
  580. function DePascalQuote(var s: string): Boolean;
  581. var
  582. destPos, sourcePos, len: Integer;
  583. t: string;
  584. ch: Char;
  585. begin
  586. DePascalQuote:= false;
  587. len:= length(s);
  588. if (len >= 1) and (s[1] = '''') then
  589. begin
  590. {Remove quotes, exchange '' against ' }
  591. destPos := 0;
  592. sourcepos:=1;
  593. while (sourcepos<len) do
  594. begin
  595. inc(sourcePos);
  596. ch := s[sourcePos];
  597. if ch = '''' then
  598. begin
  599. inc(sourcePos);
  600. if (sourcePos <= len) and (s[sourcePos] = '''') then
  601. {Add the quote as part of string}
  602. else
  603. begin
  604. SetLength(t, destPos);
  605. s:= t;
  606. Exit(true);
  607. end;
  608. end;
  609. inc(destPos);
  610. t[destPos] := ch;
  611. end;
  612. end;
  613. end;
  614. function pchar2pstring(p : pchar) : pstring;
  615. var
  616. w,i : longint;
  617. begin
  618. w:=strlen(p);
  619. for i:=w-1 downto 0 do
  620. p[i+1]:=p[i];
  621. p[0]:=chr(w);
  622. pchar2pstring:=pstring(p);
  623. end;
  624. function pstring2pchar(p : pstring) : pchar;
  625. var
  626. w,i : longint;
  627. begin
  628. w:=length(p^);
  629. for i:=1 to w do
  630. p^[i-1]:=p^[i];
  631. p^[w]:=#0;
  632. pstring2pchar:=pchar(p);
  633. end;
  634. function lowercase(c : char) : char;
  635. begin
  636. case c of
  637. #65..#90 : c := chr(ord (c) + 32);
  638. #154 : c:=#129; { german }
  639. #142 : c:=#132; { german }
  640. #153 : c:=#148; { german }
  641. #144 : c:=#130; { french }
  642. #128 : c:=#135; { french }
  643. #143 : c:=#134; { swedish/norge (?) }
  644. #165 : c:=#164; { spanish }
  645. #228 : c:=#229; { greek }
  646. #226 : c:=#231; { greek }
  647. #232 : c:=#227; { greek }
  648. end;
  649. lowercase := c;
  650. end;
  651. function strpnew(const s : string) : pchar;
  652. var
  653. p : pchar;
  654. begin
  655. getmem(p,length(s)+1);
  656. strpcopy(p,s);
  657. strpnew:=p;
  658. end;
  659. procedure strdispose(var p : pchar);
  660. begin
  661. if assigned(p) then
  662. begin
  663. freemem(p,strlen(p)+1);
  664. p:=nil;
  665. end;
  666. end;
  667. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  668. begin
  669. if assigned(p) then
  670. begin
  671. freemem(p,length(p^)+1);
  672. p:=nil;
  673. end;
  674. end;
  675. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  676. begin
  677. getmem(result,length(s)+1);
  678. result^:=s;
  679. end;
  680. function CompareText(S1, S2: string): longint;
  681. begin
  682. UpperVar(S1);
  683. UpperVar(S2);
  684. if S1<S2 then
  685. CompareText:=-1
  686. else
  687. if S1>S2 then
  688. CompareText:= 1
  689. else
  690. CompareText:=0;
  691. end;
  692. {*****************************************************************************
  693. GetSpeedValue
  694. *****************************************************************************}
  695. var
  696. Crc32Tbl : array[0..255] of cardinal;
  697. procedure MakeCRC32Tbl;
  698. var
  699. crc : cardinal;
  700. i,n : integer;
  701. begin
  702. for i:=0 to 255 do
  703. begin
  704. crc:=i;
  705. for n:=1 to 8 do
  706. if odd(longint(crc)) then
  707. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  708. else
  709. crc:=cardinal(crc shr 1);
  710. Crc32Tbl[i]:=crc;
  711. end;
  712. end;
  713. Function GetSpeedValue(Const s:String):cardinal;
  714. var
  715. i : integer;
  716. InitCrc : cardinal;
  717. begin
  718. InitCrc:=cardinal($ffffffff);
  719. for i:=1 to Length(s) do
  720. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  721. GetSpeedValue:=InitCrc;
  722. end;
  723. {*****************************************************************************
  724. Ansistring (PChar+Length)
  725. *****************************************************************************}
  726. procedure ansistringdispose(var p : pchar;length : longint);
  727. begin
  728. if assigned(p) then
  729. begin
  730. freemem(p,length+1);
  731. p:=nil;
  732. end;
  733. end;
  734. { enable ansistring comparison }
  735. { 0 means equal }
  736. { 1 means p1 > p2 }
  737. { -1 means p1 < p2 }
  738. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  739. var
  740. i,j : longint;
  741. begin
  742. compareansistrings:=0;
  743. j:=min(length1,length2);
  744. i:=0;
  745. while (i<j) do
  746. begin
  747. if p1[i]>p2[i] then
  748. begin
  749. compareansistrings:=1;
  750. exit;
  751. end
  752. else
  753. if p1[i]<p2[i] then
  754. begin
  755. compareansistrings:=-1;
  756. exit;
  757. end;
  758. inc(i);
  759. end;
  760. if length1>length2 then
  761. compareansistrings:=1
  762. else
  763. if length1<length2 then
  764. compareansistrings:=-1;
  765. end;
  766. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  767. var
  768. p : pchar;
  769. begin
  770. getmem(p,length1+length2+1);
  771. move(p1[0],p[0],length1);
  772. move(p2[0],p[length1],length2+1);
  773. concatansistrings:=p;
  774. end;
  775. {*****************************************************************************
  776. Ultra basic KISS Lzw (de)compressor
  777. *****************************************************************************}
  778. {This is an extremely basic implementation of the Lzw algorithm. It
  779. compresses 7-bit ASCII strings into 8-bit compressed strings.
  780. The Lzw dictionary is preinitialized with 0..127, therefore this
  781. part of the dictionary does not need to be stored in the arrays.
  782. The Lzw code size is allways 8 bit, so we do not need complex code
  783. that can write partial bytes.}
  784. function minilzw_encode(const s:string):string;
  785. var t,u,i:byte;
  786. c:char;
  787. data:array[128..255] of char;
  788. previous:array[128..255] of byte;
  789. lzwptr:byte;
  790. next_avail:set of 0..255;
  791. label l1;
  792. begin
  793. minilzw_encode:='';
  794. if s<>'' then
  795. begin
  796. lzwptr:=127;
  797. t:=byte(s[1]);
  798. i:=2;
  799. u:=128;
  800. next_avail:=[];
  801. while i<=length(s) do
  802. begin
  803. c:=s[i];
  804. if not(t in next_avail) or (u>lzwptr) then goto l1;
  805. while (previous[u]<>t) or (data[u]<>c) do
  806. begin
  807. inc(u);
  808. if u>lzwptr then goto l1;
  809. end;
  810. t:=u;
  811. inc(i);
  812. continue;
  813. l1:
  814. {It's a pity that we still need those awfull tricks
  815. with this modern compiler. Without this performance
  816. of the entire procedure drops about 3 times.}
  817. inc(minilzw_encode[0]);
  818. minilzw_encode[length(minilzw_encode)]:=char(t);
  819. if lzwptr=255 then
  820. begin
  821. lzwptr:=127;
  822. next_avail:=[];
  823. end
  824. else
  825. begin
  826. inc(lzwptr);
  827. data[lzwptr]:=c;
  828. previous[lzwptr]:=t;
  829. include(next_avail,t);
  830. end;
  831. t:=byte(c);
  832. u:=128;
  833. inc(i);
  834. end;
  835. inc(minilzw_encode[0]);
  836. minilzw_encode[length(minilzw_encode)]:=char(t);
  837. end;
  838. end;
  839. function minilzw_decode(const s:string):string;
  840. var oldc,newc,c:char;
  841. i,j:byte;
  842. data:array[128..255] of char;
  843. previous:array[128..255] of byte;
  844. lzwptr:byte;
  845. t:string;
  846. begin
  847. minilzw_decode:='';
  848. if s<>'' then
  849. begin
  850. lzwptr:=127;
  851. oldc:=s[1];
  852. c:=oldc;
  853. i:=2;
  854. minilzw_decode:=oldc;
  855. while i<=length(s) do
  856. begin
  857. newc:=s[i];
  858. if byte(newc)>lzwptr then
  859. begin
  860. t:=c;
  861. c:=oldc;
  862. end
  863. else
  864. begin
  865. c:=newc;
  866. t:='';
  867. end;
  868. while c>=#128 do
  869. begin
  870. inc(t[0]);
  871. t[length(t)]:=data[byte(c)];
  872. byte(c):=previous[byte(c)];
  873. end;
  874. inc(minilzw_decode[0]);
  875. minilzw_decode[length(minilzw_decode)]:=c;
  876. for j:=length(t) downto 1 do
  877. begin
  878. inc(minilzw_decode[0]);
  879. minilzw_decode[length(minilzw_decode)]:=t[j];
  880. end;
  881. if lzwptr=255 then
  882. lzwptr:=127
  883. else
  884. begin
  885. inc(lzwptr);
  886. previous[lzwptr]:=byte(oldc);
  887. data[lzwptr]:=c;
  888. end;
  889. oldc:=newc;
  890. inc(i);
  891. end;
  892. end;
  893. end;
  894. procedure defaulterror(i:longint);
  895. begin
  896. writeln('Internal error ',i);
  897. runerror(255);
  898. end;
  899. initialization
  900. internalerrorproc:=@defaulterror;
  901. makecrc32tbl;
  902. initupperlower;
  903. end.