cutils.pas 32 KB

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