cutils.pas 27 KB

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