cutils.pas 27 KB

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