cutils.pas 29 KB

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