cutils.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements some support functions
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published
  7. by the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {# This unit contains some generic support functions which are used
  19. in the different parts of the compiler.
  20. }
  21. unit cutils;
  22. {$i fpcdefs.inc}
  23. interface
  24. type
  25. {$ifdef ver1_0}
  26. ptrint = longint;
  27. {$endif ver1_0}
  28. pstring = ^string;
  29. get_var_value_proc=function(const s:string):string of object;
  30. Tcharset=set of char;
  31. {# Returns the minimal value between @var(a) and @var(b) }
  32. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  33. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  34. {# Returns the maximum value between @var(a) and @var(b) }
  35. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  36. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  37. {# Returns the value in @var(x) swapped to different endian }
  38. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  39. {# Returns the value in @var(x) swapped to different endian }
  40. function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  41. {# Returns the value in @va(x) swapped to different endian }
  42. function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
  43. {# Return value @var(i) aligned on @var(a) boundary }
  44. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  45. function used_align(varalign,minalign,maxalign:longint):longint;
  46. function size_2_align(len : longint) : longint;
  47. procedure Replace(var s:string;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 hexstr(val : cardinal;cnt : cardinal) : 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. procedure valint(S : string;var V : longint;var code : integer);
  65. {# Returns true if the string s is a number }
  66. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  67. {# Returns true if value is a power of 2, the actual
  68. exponent value is returned in power.
  69. }
  70. function ispowerof2(value : int64;var power : longint) : boolean;
  71. function backspace_quote(const s:string;const qchars:Tcharset):string;
  72. function octal_quote(const s:string;const qchars:Tcharset):string;
  73. function maybequoted(const s:string):string;
  74. function CompareText(S1, S2: string): longint;
  75. { releases the string p and assignes nil to p }
  76. { if p=nil then freemem isn't called }
  77. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  78. { allocates mem for a copy of s, copies s to this mem and returns }
  79. { a pointer to this mem }
  80. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  81. {# Allocates memory for the string @var(s) and copies s as zero
  82. terminated string to that allocated memory and returns a pointer
  83. to that mem
  84. }
  85. function strpnew(const s : string) : pchar;
  86. procedure strdispose(var p : pchar);
  87. function string_evaluate(s:string;get_var_value:get_var_value_proc;
  88. const vars:array of string):Pchar;
  89. {# makes the character @var(c) lowercase, with spanish, french and german
  90. character set
  91. }
  92. function lowercase(c : char) : char;
  93. { makes zero terminated string to a pascal string }
  94. { the data in p is modified and p is returned }
  95. function pchar2pstring(p : pchar) : pstring;
  96. { ambivalent to pchar2pstring }
  97. function pstring2pchar(p : pstring) : pchar;
  98. { Speed/Hash value }
  99. Function GetSpeedValue(Const s:String):cardinal;
  100. { Ansistring (pchar+length) support }
  101. procedure ansistringdispose(var p : pchar;length : longint);
  102. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  103. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  104. function DeleteFile(const fn:string):boolean;
  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. {$ifdef delphi}
  111. sysutils
  112. {$else}
  113. strings
  114. {$endif}
  115. ;
  116. var
  117. uppertbl,
  118. lowertbl : array[char] of char;
  119. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  120. {
  121. return the minimal of a and b
  122. }
  123. begin
  124. if a>b then
  125. min:=b
  126. else
  127. min:=a;
  128. end;
  129. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  130. {
  131. return the minimal of a and b
  132. }
  133. begin
  134. if a>b then
  135. min:=b
  136. else
  137. min:=a;
  138. end;
  139. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  140. {
  141. return the maximum of a and b
  142. }
  143. begin
  144. if a<b then
  145. max:=b
  146. else
  147. max:=a;
  148. end;
  149. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  150. {
  151. return the maximum of a and b
  152. }
  153. begin
  154. if a<b then
  155. max:=b
  156. else
  157. max:=a;
  158. end;
  159. Function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  160. var
  161. y : word;
  162. z : word;
  163. Begin
  164. y := x shr 16;
  165. y := word(longint(y) shl 8) or (y shr 8);
  166. z := x and $FFFF;
  167. z := word(longint(z) shl 8) or (z shr 8);
  168. SwapLong := (longint(z) shl 16) or longint(y);
  169. End;
  170. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  171. Begin
  172. result:=swaplong(hi(x));
  173. result:=result or (swaplong(lo(x)) shl 32);
  174. End;
  175. Function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
  176. var
  177. z : byte;
  178. Begin
  179. z := x shr 8;
  180. x := x and $ff;
  181. x := (x shl 8);
  182. SwapWord := x or z;
  183. End;
  184. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  185. {
  186. return value <i> aligned <a> boundary
  187. }
  188. begin
  189. { for 0 and 1 no aligning is needed }
  190. if a<=1 then
  191. result:=i
  192. else
  193. begin
  194. if i<0 then
  195. result:=((i-a+1) div a) * a
  196. else
  197. result:=((i+a-1) div a) * a;
  198. end;
  199. end;
  200. function size_2_align(len : longint) : longint;
  201. begin
  202. if len>16 then
  203. size_2_align:=32
  204. else if len>8 then
  205. size_2_align:=16
  206. else if len>4 then
  207. size_2_align:=8
  208. else if len>2 then
  209. size_2_align:=4
  210. else if len>1 then
  211. size_2_align:=2
  212. else
  213. size_2_align:=1;
  214. end;
  215. function used_align(varalign,minalign,maxalign:longint):longint;
  216. begin
  217. { varalign : minimum alignment required for the variable
  218. minalign : Minimum alignment of this structure, 0 = undefined
  219. maxalign : Maximum alignment of this structure, 0 = undefined }
  220. if (minalign>0) and
  221. (varalign<minalign) then
  222. used_align:=minalign
  223. else
  224. begin
  225. if (maxalign>0) and
  226. (varalign>maxalign) then
  227. used_align:=maxalign
  228. else
  229. used_align:=varalign;
  230. end;
  231. end;
  232. procedure Replace(var s:string;s1:string;const s2:string);
  233. var
  234. last,
  235. i : longint;
  236. begin
  237. s1:=upper(s1);
  238. last:=0;
  239. repeat
  240. i:=pos(s1,upper(s));
  241. if i=last then
  242. i:=0;
  243. if (i>0) then
  244. begin
  245. Delete(s,i,length(s1));
  246. Insert(s2,s,i);
  247. last:=i;
  248. end;
  249. until (i=0);
  250. end;
  251. procedure ReplaceCase(var s:string;const s1,s2:string);
  252. var
  253. last,
  254. i : longint;
  255. begin
  256. last:=0;
  257. repeat
  258. i:=pos(s1,s);
  259. if i=last then
  260. i:=0;
  261. if (i>0) then
  262. begin
  263. Delete(s,i,length(s1));
  264. Insert(s2,s,i);
  265. last:=i;
  266. end;
  267. until (i=0);
  268. end;
  269. function upper(const s : string) : string;
  270. {
  271. return uppercased string of s
  272. }
  273. var
  274. i : longint;
  275. begin
  276. for i:=1 to length(s) do
  277. upper[i]:=uppertbl[s[i]];
  278. upper[0]:=s[0];
  279. end;
  280. function lower(const s : string) : string;
  281. {
  282. return lowercased string of s
  283. }
  284. var
  285. i : longint;
  286. begin
  287. for i:=1 to length(s) do
  288. lower[i]:=lowertbl[s[i]];
  289. lower[0]:=s[0];
  290. end;
  291. procedure uppervar(var s : string);
  292. {
  293. uppercase string s
  294. }
  295. var
  296. i : longint;
  297. begin
  298. for i:=1 to length(s) do
  299. s[i]:=uppertbl[s[i]];
  300. end;
  301. procedure initupperlower;
  302. var
  303. c : char;
  304. begin
  305. for c:=#0 to #255 do
  306. begin
  307. lowertbl[c]:=c;
  308. uppertbl[c]:=c;
  309. case c of
  310. 'A'..'Z' :
  311. lowertbl[c]:=char(byte(c)+32);
  312. 'a'..'z' :
  313. uppertbl[c]:=char(byte(c)-32);
  314. end;
  315. end;
  316. end;
  317. function hexstr(val : cardinal;cnt : cardinal) : string;
  318. const
  319. HexTbl : array[0..15] of char='0123456789ABCDEF';
  320. var
  321. i,j : cardinal;
  322. begin
  323. { calculate required length }
  324. i:=0;
  325. j:=val;
  326. while (j>0) do
  327. begin
  328. inc(i);
  329. j:=j shr 4;
  330. end;
  331. { generate fillers }
  332. j:=0;
  333. while (i+j<cnt) do
  334. begin
  335. inc(j);
  336. hexstr[j]:='0';
  337. end;
  338. { generate hex }
  339. inc(j,i);
  340. hexstr[0]:=chr(j);
  341. while (val>0) do
  342. begin
  343. hexstr[j]:=hextbl[val and $f];
  344. dec(j);
  345. val:=val shr 4;
  346. end;
  347. end;
  348. function DStr(l:longint):string;
  349. var
  350. TmpStr : string[32];
  351. i : longint;
  352. begin
  353. Str(l,TmpStr);
  354. i:=Length(TmpStr);
  355. while (i>3) do
  356. begin
  357. dec(i,3);
  358. if TmpStr[i]<>'-' then
  359. insert('.',TmpStr,i+1);
  360. end;
  361. DStr:=TmpStr;
  362. end;
  363. function trimbspace(const s:string):string;
  364. {
  365. return s with all leading spaces and tabs removed
  366. }
  367. var
  368. i,j : longint;
  369. begin
  370. j:=1;
  371. i:=length(s);
  372. while (j<i) and (s[j] in [#9,' ']) do
  373. inc(j);
  374. trimbspace:=Copy(s,j,i-j+1);
  375. end;
  376. function trimspace(const s:string):string;
  377. {
  378. return s with all leading and ending spaces and tabs removed
  379. }
  380. var
  381. i,j : longint;
  382. begin
  383. i:=length(s);
  384. while (i>0) and (s[i] in [#9,' ']) do
  385. dec(i);
  386. j:=1;
  387. while (j<i) and (s[j] in [#9,' ']) do
  388. inc(j);
  389. trimspace:=Copy(s,j,i-j+1);
  390. end;
  391. function space (b : longint): string;
  392. var
  393. s: string;
  394. begin
  395. space[0] := chr(b);
  396. s[0] := chr(b);
  397. FillChar (S[1],b,' ');
  398. space:=s;
  399. end;
  400. function PadSpace(const s:string;len:longint):string;
  401. {
  402. return s with spaces add to the end
  403. }
  404. begin
  405. if length(s)<len then
  406. PadSpace:=s+Space(len-length(s))
  407. else
  408. PadSpace:=s;
  409. end;
  410. function GetToken(var s:string;endchar:char):string;
  411. var
  412. i : longint;
  413. begin
  414. GetToken:='';
  415. s:=TrimSpace(s);
  416. if s[1]='''' then
  417. begin
  418. i:=1;
  419. while (i<length(s)) do
  420. begin
  421. inc(i);
  422. if s[i]='''' then
  423. begin
  424. { Remove double quote }
  425. if (i<length(s)) and
  426. (s[i+1]='''') then
  427. begin
  428. Delete(s,i,1);
  429. inc(i);
  430. end
  431. else
  432. begin
  433. GetToken:=Copy(s,2,i-2);
  434. Delete(s,1,i);
  435. exit;
  436. end;
  437. end;
  438. end;
  439. GetToken:=s;
  440. s:='';
  441. end
  442. else
  443. begin
  444. i:=pos(EndChar,s);
  445. if i=0 then
  446. begin
  447. GetToken:=s;
  448. s:='';
  449. exit;
  450. end
  451. else
  452. begin
  453. GetToken:=Copy(s,1,i-1);
  454. Delete(s,1,i);
  455. exit;
  456. end;
  457. end;
  458. end;
  459. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  460. begin
  461. str(e,result);
  462. end;
  463. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  464. {
  465. return string of value i
  466. }
  467. begin
  468. str(i,result);
  469. end;
  470. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  471. {
  472. return string of value i
  473. }
  474. begin
  475. str(i,result);
  476. end;
  477. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  478. {
  479. return string of value i
  480. }
  481. begin
  482. str(i,result);
  483. end;
  484. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  485. {
  486. return string of value i, but always include a + when i>=0
  487. }
  488. begin
  489. str(i,result);
  490. if i>=0 then
  491. result:='+'+result;
  492. end;
  493. procedure valint(S : string;var V : longint;var code : integer);
  494. {
  495. val() with support for octal, which is not supported under tp7
  496. }
  497. {$ifndef FPC}
  498. var
  499. vs : longint;
  500. c : byte;
  501. begin
  502. if s[1]='%' then
  503. begin
  504. vs:=0;
  505. longint(v):=0;
  506. for c:=2 to length(s) do
  507. begin
  508. if s[c]='0' then
  509. vs:=vs shl 1
  510. else
  511. if s[c]='1' then
  512. vs:=vs shl 1+1
  513. else
  514. begin
  515. code:=c;
  516. exit;
  517. end;
  518. end;
  519. code:=0;
  520. longint(v):=vs;
  521. end
  522. else
  523. system.val(S,V,code);
  524. end;
  525. {$else not FPC}
  526. begin
  527. system.val(S,V,code);
  528. end;
  529. {$endif not FPC}
  530. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  531. {
  532. is string a correct number ?
  533. }
  534. var
  535. w : integer;
  536. l : longint;
  537. begin
  538. valint(s,l,w);
  539. is_number:=(w=0);
  540. end;
  541. function ispowerof2(value : int64;var power : longint) : boolean;
  542. {
  543. return if value is a power of 2. And if correct return the power
  544. }
  545. var
  546. hl : int64;
  547. i : longint;
  548. begin
  549. if value and (value - 1) <> 0 then
  550. begin
  551. ispowerof2 := false;
  552. exit
  553. end;
  554. hl:=1;
  555. ispowerof2:=true;
  556. for i:=0 to 63 do
  557. begin
  558. if hl=value then
  559. begin
  560. power:=i;
  561. exit;
  562. end;
  563. hl:=hl shl 1;
  564. end;
  565. ispowerof2:=false;
  566. end;
  567. function backspace_quote(const s:string;const qchars:Tcharset):string;
  568. var i:byte;
  569. begin
  570. backspace_quote:='';
  571. for i:=1 to length(s) do
  572. begin
  573. if (s[i]=#10) and (#10 in qchars) then
  574. backspace_quote:=backspace_quote+'\n'
  575. else if (s[i]=#13) and (#13 in qchars) then
  576. backspace_quote:=backspace_quote+'\r'
  577. else
  578. begin
  579. if s[i] in qchars then
  580. backspace_quote:=backspace_quote+'\';
  581. backspace_quote:=backspace_quote+s[i];
  582. end;
  583. end;
  584. end;
  585. function octal_quote(const s:string;const qchars:Tcharset):string;
  586. var i:byte;
  587. begin
  588. octal_quote:='';
  589. for i:=1 to length(s) do
  590. begin
  591. if s[i] in qchars then
  592. begin
  593. if ord(s[i])<64 then
  594. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  595. else
  596. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  597. end
  598. else
  599. octal_quote:=octal_quote+s[i];
  600. end;
  601. end;
  602. function maybequoted(const s:string):string;
  603. var
  604. s1 : string;
  605. i : integer;
  606. quoted : boolean;
  607. begin
  608. quoted:=false;
  609. s1:='"';
  610. for i:=1 to length(s) do
  611. begin
  612. case s[i] of
  613. '"' :
  614. begin
  615. quoted:=true;
  616. s1:=s1+'\"';
  617. end;
  618. ' ',
  619. #128..#255 :
  620. begin
  621. quoted:=true;
  622. s1:=s1+s[i];
  623. end;
  624. else
  625. s1:=s1+s[i];
  626. end;
  627. end;
  628. if quoted then
  629. maybequoted:=s1+'"'
  630. else
  631. maybequoted:=s;
  632. end;
  633. function pchar2pstring(p : pchar) : pstring;
  634. var
  635. w,i : longint;
  636. begin
  637. w:=strlen(p);
  638. for i:=w-1 downto 0 do
  639. p[i+1]:=p[i];
  640. p[0]:=chr(w);
  641. pchar2pstring:=pstring(p);
  642. end;
  643. function pstring2pchar(p : pstring) : pchar;
  644. var
  645. w,i : longint;
  646. begin
  647. w:=length(p^);
  648. for i:=1 to w do
  649. p^[i-1]:=p^[i];
  650. p^[w]:=#0;
  651. pstring2pchar:=pchar(p);
  652. end;
  653. function lowercase(c : char) : char;
  654. begin
  655. case c of
  656. #65..#90 : c := chr(ord (c) + 32);
  657. #154 : c:=#129; { german }
  658. #142 : c:=#132; { german }
  659. #153 : c:=#148; { german }
  660. #144 : c:=#130; { french }
  661. #128 : c:=#135; { french }
  662. #143 : c:=#134; { swedish/norge (?) }
  663. #165 : c:=#164; { spanish }
  664. #228 : c:=#229; { greek }
  665. #226 : c:=#231; { greek }
  666. #232 : c:=#227; { greek }
  667. end;
  668. lowercase := c;
  669. end;
  670. function strpnew(const s : string) : pchar;
  671. var
  672. p : pchar;
  673. begin
  674. getmem(p,length(s)+1);
  675. strpcopy(p,s);
  676. strpnew:=p;
  677. end;
  678. procedure strdispose(var p : pchar);
  679. begin
  680. if assigned(p) then
  681. begin
  682. freemem(p,strlen(p)+1);
  683. p:=nil;
  684. end;
  685. end;
  686. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  687. begin
  688. if assigned(p) then
  689. begin
  690. freemem(p,length(p^)+1);
  691. p:=nil;
  692. end;
  693. end;
  694. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  695. begin
  696. getmem(result,length(s)+1);
  697. result^:=s;
  698. end;
  699. function CompareText(S1, S2: string): longint;
  700. begin
  701. UpperVar(S1);
  702. UpperVar(S2);
  703. if S1<S2 then
  704. CompareText:=-1
  705. else
  706. if S1>S2 then
  707. CompareText:= 1
  708. else
  709. CompareText:=0;
  710. end;
  711. function string_evaluate(s:string;get_var_value:get_var_value_proc;
  712. const vars:array of string):Pchar;
  713. {S contains a prototype of a stabstring. Stabstr_evaluate will expand
  714. variables and parameters.
  715. Output is s in ASCIIZ format, with the following expanded:
  716. ${varname} - The variable name is expanded.
  717. $n - The parameter n is expanded.
  718. $$ - Is expanded to $
  719. }
  720. const maxvalue=9;
  721. maxdata=1023;
  722. var i,j:byte;
  723. varname:string[63];
  724. varno,varcounter:byte;
  725. varvalues:array[0..9] of Pstring;
  726. {1 kb of parameters is the limit. 256 extra bytes are allocated to
  727. ensure buffer integrity.}
  728. varvaluedata:array[0..maxdata+256] of char;
  729. varptr:Pchar;
  730. len:cardinal;
  731. r:Pchar;
  732. begin
  733. {Two pass approach, first, calculate the length and receive variables.}
  734. i:=1;
  735. len:=0;
  736. varcounter:=0;
  737. varptr:=@varvaluedata;
  738. while i<=length(s) do
  739. begin
  740. if (s[i]='$') and (i<length(s)) then
  741. begin
  742. if s[i+1]='$' then
  743. begin
  744. inc(len);
  745. inc(i);
  746. end
  747. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  748. begin
  749. varname:='';
  750. inc(i,2);
  751. repeat
  752. inc(varname[0]);
  753. varname[length(varname)]:=s[i];
  754. s[i]:=char(varcounter);
  755. inc(i);
  756. until s[i]='}';
  757. varvalues[varcounter]:=Pstring(varptr);
  758. if varptr>@varvaluedata+maxdata then
  759. runerror($8001); {No internalerror available}
  760. Pstring(varptr)^:=get_var_value(varname);
  761. inc(len,length(Pstring(varptr)^));
  762. inc(varptr,length(Pstring(varptr)^)+1);
  763. inc(varcounter);
  764. end
  765. else if s[i+1] in ['0'..'9'] then
  766. begin
  767. inc(len,length(vars[byte(s[i+1])-byte('1')]));
  768. inc(i);
  769. end;
  770. end
  771. else
  772. inc(len);
  773. inc(i);
  774. end;
  775. {Second pass, writeout stabstring.}
  776. getmem(r,len+1);
  777. string_evaluate:=r;
  778. i:=1;
  779. while i<=length(s) do
  780. begin
  781. if (s[i]='$') and (i<length(s)) then
  782. begin
  783. if s[i+1]='$' then
  784. begin
  785. r^:='$';
  786. inc(r);
  787. inc(i);
  788. end
  789. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  790. begin
  791. varname:='';
  792. inc(i,2);
  793. varno:=byte(s[i]);
  794. repeat
  795. inc(i);
  796. until s[i]='}';
  797. for j:=1 to length(varvalues[varno]^) do
  798. begin
  799. r^:=varvalues[varno]^[j];
  800. inc(r);
  801. end;
  802. end
  803. else if s[i+1] in ['0'..'9'] then
  804. begin
  805. for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
  806. begin
  807. r^:=vars[byte(s[i+1])-byte('1')][j];
  808. inc(r);
  809. end;
  810. inc(i);
  811. end
  812. end
  813. else
  814. begin
  815. r^:=s[i];
  816. inc(r);
  817. end;
  818. inc(i);
  819. end;
  820. r^:=#0;
  821. end;
  822. {*****************************************************************************
  823. GetSpeedValue
  824. *****************************************************************************}
  825. {$ifdef ver1_0}
  826. {$R-}
  827. {$endif}
  828. var
  829. Crc32Tbl : array[0..255] of cardinal;
  830. procedure MakeCRC32Tbl;
  831. var
  832. crc : cardinal;
  833. i,n : integer;
  834. begin
  835. for i:=0 to 255 do
  836. begin
  837. crc:=i;
  838. for n:=1 to 8 do
  839. if odd(longint(crc)) then
  840. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  841. else
  842. crc:=cardinal(crc shr 1);
  843. Crc32Tbl[i]:=crc;
  844. end;
  845. end;
  846. Function GetSpeedValue(Const s:String):cardinal;
  847. var
  848. i : integer;
  849. InitCrc : cardinal;
  850. begin
  851. InitCrc:=cardinal($ffffffff);
  852. for i:=1 to Length(s) do
  853. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  854. GetSpeedValue:=InitCrc;
  855. end;
  856. {*****************************************************************************
  857. Ansistring (PChar+Length)
  858. *****************************************************************************}
  859. procedure ansistringdispose(var p : pchar;length : longint);
  860. begin
  861. if assigned(p) then
  862. begin
  863. freemem(p,length+1);
  864. p:=nil;
  865. end;
  866. end;
  867. { enable ansistring comparison }
  868. { 0 means equal }
  869. { 1 means p1 > p2 }
  870. { -1 means p1 < p2 }
  871. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  872. var
  873. i,j : longint;
  874. begin
  875. compareansistrings:=0;
  876. j:=min(length1,length2);
  877. i:=0;
  878. while (i<j) do
  879. begin
  880. if p1[i]>p2[i] then
  881. begin
  882. compareansistrings:=1;
  883. exit;
  884. end
  885. else
  886. if p1[i]<p2[i] then
  887. begin
  888. compareansistrings:=-1;
  889. exit;
  890. end;
  891. inc(i);
  892. end;
  893. if length1>length2 then
  894. compareansistrings:=1
  895. else
  896. if length1<length2 then
  897. compareansistrings:=-1;
  898. end;
  899. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  900. var
  901. p : pchar;
  902. begin
  903. getmem(p,length1+length2+1);
  904. move(p1[0],p[0],length1);
  905. move(p2[0],p[length1],length2+1);
  906. concatansistrings:=p;
  907. end;
  908. {*****************************************************************************
  909. File Functions
  910. *****************************************************************************}
  911. function DeleteFile(const fn:string):boolean;
  912. var
  913. f : file;
  914. begin
  915. {$I-}
  916. assign(f,fn);
  917. erase(f);
  918. {$I-}
  919. DeleteFile:=(IOResult=0);
  920. end;
  921. {*****************************************************************************
  922. Ultra basic KISS Lzw (de)compressor
  923. *****************************************************************************}
  924. {This is an extremely basic implementation of the Lzw algorithm. It
  925. compresses 7-bit ASCII strings into 8-bit compressed strings.
  926. The Lzw dictionary is preinitialized with 0..127, therefore this
  927. part of the dictionary does not need to be stored in the arrays.
  928. The Lzw code size is allways 8 bit, so we do not need complex code
  929. that can write partial bytes.}
  930. function minilzw_encode(const s:string):string;
  931. var t,u,i:byte;
  932. c:char;
  933. data:array[128..255] of char;
  934. previous:array[128..255] of byte;
  935. lzwptr:byte;
  936. next_avail:set of 0..255;
  937. label l1;
  938. begin
  939. minilzw_encode:='';
  940. if s<>'' then
  941. begin
  942. lzwptr:=127;
  943. t:=byte(s[1]);
  944. i:=2;
  945. u:=128;
  946. next_avail:=[];
  947. while i<=length(s) do
  948. begin
  949. c:=s[i];
  950. if not(t in next_avail) or (u>lzwptr) then goto l1;
  951. while (previous[u]<>t) or (data[u]<>c) do
  952. begin
  953. inc(u);
  954. if u>lzwptr then goto l1;
  955. end;
  956. t:=u;
  957. inc(i);
  958. continue;
  959. l1:
  960. {It's a pity that we still need those awfull tricks
  961. with this modern compiler. Without this performance
  962. of the entire procedure drops about 3 times.}
  963. inc(minilzw_encode[0]);
  964. minilzw_encode[length(minilzw_encode)]:=char(t);
  965. if lzwptr=255 then
  966. begin
  967. lzwptr:=127;
  968. next_avail:=[];
  969. end
  970. else
  971. begin
  972. inc(lzwptr);
  973. data[lzwptr]:=c;
  974. previous[lzwptr]:=t;
  975. include(next_avail,t);
  976. end;
  977. t:=byte(c);
  978. u:=128;
  979. inc(i);
  980. end;
  981. inc(minilzw_encode[0]);
  982. minilzw_encode[length(minilzw_encode)]:=char(t);
  983. end;
  984. end;
  985. function minilzw_decode(const s:string):string;
  986. var oldc,newc,c:char;
  987. i,j:byte;
  988. data:array[128..255] of char;
  989. previous:array[128..255] of byte;
  990. lzwptr:byte;
  991. t:string;
  992. begin
  993. minilzw_decode:='';
  994. if s<>'' then
  995. begin
  996. lzwptr:=127;
  997. oldc:=s[1];
  998. c:=oldc;
  999. i:=2;
  1000. minilzw_decode:=oldc;
  1001. while i<=length(s) do
  1002. begin
  1003. newc:=s[i];
  1004. if byte(newc)>lzwptr then
  1005. begin
  1006. t:=c;
  1007. c:=oldc;
  1008. end
  1009. else
  1010. begin
  1011. c:=newc;
  1012. t:='';
  1013. end;
  1014. while c>=#128 do
  1015. begin
  1016. inc(t[0]);
  1017. t[length(t)]:=data[byte(c)];
  1018. byte(c):=previous[byte(c)];
  1019. end;
  1020. inc(minilzw_decode[0]);
  1021. minilzw_decode[length(minilzw_decode)]:=c;
  1022. for j:=length(t) downto 1 do
  1023. begin
  1024. inc(minilzw_decode[0]);
  1025. minilzw_decode[length(minilzw_decode)]:=t[j];
  1026. end;
  1027. if lzwptr=255 then
  1028. lzwptr:=127
  1029. else
  1030. begin
  1031. inc(lzwptr);
  1032. previous[lzwptr]:=byte(oldc);
  1033. data[lzwptr]:=c;
  1034. end;
  1035. oldc:=newc;
  1036. inc(i);
  1037. end;
  1038. end;
  1039. end;
  1040. initialization
  1041. makecrc32tbl;
  1042. initupperlower;
  1043. end.
  1044. {
  1045. $Log$
  1046. Revision 1.41 2004-06-20 08:55:29 florian
  1047. * logs truncated
  1048. Revision 1.40 2004/06/16 20:07:07 florian
  1049. * dwarf branch merged
  1050. Revision 1.39 2004/05/22 23:33:18 peter
  1051. fix range check error when array size > maxlongint
  1052. Revision 1.38.2.3 2004/04/29 19:07:22 peter
  1053. * compile fixes
  1054. Revision 1.38.2.2 2004/04/26 21:01:36 peter
  1055. * aint fixes
  1056. Revision 1.38.2.1 2004/04/20 16:35:58 peter
  1057. * generate dwarf for stackframe entry
  1058. }