cutils.pas 28 KB

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