cutils.pas 32 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241
  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. {Lzw encode/decode to compress strings -> save memory.}
  118. function minilzw_encode(const s:string):string;
  119. function minilzw_decode(const s:string):string;
  120. implementation
  121. uses
  122. strings
  123. ;
  124. {$ifndef HASGETFPCHEAPSTATUS}
  125. function GetFPCHeapStatus:TFPCHeapStatus;
  126. begin
  127. GetHeapStatus(result);
  128. end;
  129. {$endif HASGETFPCHEAPSTATUS}
  130. var
  131. uppertbl,
  132. lowertbl : array[char] of char;
  133. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  134. {
  135. return the minimal of a and b
  136. }
  137. begin
  138. if a>b then
  139. min:=b
  140. else
  141. min:=a;
  142. end;
  143. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  144. {
  145. return the minimal of a and b
  146. }
  147. begin
  148. if a>b then
  149. min:=b
  150. else
  151. min:=a;
  152. end;
  153. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  154. {
  155. return the maximum of a and b
  156. }
  157. begin
  158. if a<b then
  159. max:=b
  160. else
  161. max:=a;
  162. end;
  163. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  164. {
  165. return the maximum of a and b
  166. }
  167. begin
  168. if a<b then
  169. max:=b
  170. else
  171. max:=a;
  172. end;
  173. Function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  174. var
  175. y : word;
  176. z : word;
  177. Begin
  178. y := x shr 16;
  179. y := word(longint(y) shl 8) or (y shr 8);
  180. z := x and $FFFF;
  181. z := word(longint(z) shl 8) or (z shr 8);
  182. SwapLong := (longint(z) shl 16) or longint(y);
  183. End;
  184. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  185. Begin
  186. result:=swaplong(longint(hi(x)));
  187. result:=result or (swaplong(longint(lo(x))) shl 32);
  188. End;
  189. Function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
  190. var
  191. z : byte;
  192. Begin
  193. z := x shr 8;
  194. x := x and $ff;
  195. x := (x shl 8);
  196. SwapWord := x or z;
  197. End;
  198. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  199. {
  200. return value <i> aligned <a> boundary
  201. }
  202. begin
  203. { for 0 and 1 no aligning is needed }
  204. if a<=1 then
  205. result:=i
  206. else
  207. begin
  208. if i<0 then
  209. result:=((i-a+1) div a) * a
  210. else
  211. result:=((i+a-1) div a) * a;
  212. end;
  213. end;
  214. function size_2_align(len : longint) : longint;
  215. begin
  216. if len>16 then
  217. size_2_align:=32
  218. else if len>8 then
  219. size_2_align:=16
  220. else if len>4 then
  221. size_2_align:=8
  222. else if len>2 then
  223. size_2_align:=4
  224. else if len>1 then
  225. size_2_align:=2
  226. else
  227. size_2_align:=1;
  228. end;
  229. function used_align(varalign,minalign,maxalign:longint):longint;
  230. begin
  231. { varalign : minimum alignment required for the variable
  232. minalign : Minimum alignment of this structure, 0 = undefined
  233. maxalign : Maximum alignment of this structure, 0 = undefined }
  234. if (minalign>0) and
  235. (varalign<minalign) then
  236. used_align:=minalign
  237. else
  238. begin
  239. if (maxalign>0) and
  240. (varalign>maxalign) then
  241. used_align:=maxalign
  242. else
  243. used_align:=varalign;
  244. end;
  245. end;
  246. procedure Replace(var s:string;s1:string;const s2:string);
  247. var
  248. last,
  249. i : longint;
  250. begin
  251. s1:=upper(s1);
  252. last:=0;
  253. repeat
  254. i:=pos(s1,upper(s));
  255. if i=last then
  256. i:=0;
  257. if (i>0) then
  258. begin
  259. Delete(s,i,length(s1));
  260. Insert(s2,s,i);
  261. last:=i;
  262. end;
  263. until (i=0);
  264. end;
  265. procedure Replace(var s:AnsiString;s1:string;const s2:string);
  266. var
  267. last,
  268. i : longint;
  269. begin
  270. s1:=upper(s1);
  271. last:=0;
  272. repeat
  273. i:=pos(s1,upper(s));
  274. if i=last then
  275. i:=0;
  276. if (i>0) then
  277. begin
  278. Delete(s,i,length(s1));
  279. Insert(s2,s,i);
  280. last:=i;
  281. end;
  282. until (i=0);
  283. end;
  284. procedure ReplaceCase(var s:string;const s1,s2:string);
  285. var
  286. last,
  287. i : longint;
  288. begin
  289. last:=0;
  290. repeat
  291. i:=pos(s1,s);
  292. if i=last then
  293. i:=0;
  294. if (i>0) then
  295. begin
  296. Delete(s,i,length(s1));
  297. Insert(s2,s,i);
  298. last:=i;
  299. end;
  300. until (i=0);
  301. end;
  302. function upper(const s : string) : string;
  303. {
  304. return uppercased string of s
  305. }
  306. var
  307. i : longint;
  308. begin
  309. for i:=1 to length(s) do
  310. upper[i]:=uppertbl[s[i]];
  311. upper[0]:=s[0];
  312. end;
  313. function lower(const s : string) : string;
  314. {
  315. return lowercased string of s
  316. }
  317. var
  318. i : longint;
  319. begin
  320. for i:=1 to length(s) do
  321. lower[i]:=lowertbl[s[i]];
  322. lower[0]:=s[0];
  323. end;
  324. procedure uppervar(var s : string);
  325. {
  326. uppercase string s
  327. }
  328. var
  329. i : longint;
  330. begin
  331. for i:=1 to length(s) do
  332. s[i]:=uppertbl[s[i]];
  333. end;
  334. procedure initupperlower;
  335. var
  336. c : char;
  337. begin
  338. for c:=#0 to #255 do
  339. begin
  340. lowertbl[c]:=c;
  341. uppertbl[c]:=c;
  342. case c of
  343. 'A'..'Z' :
  344. lowertbl[c]:=char(byte(c)+32);
  345. 'a'..'z' :
  346. uppertbl[c]:=char(byte(c)-32);
  347. end;
  348. end;
  349. end;
  350. function hexstr(val : cardinal;cnt : cardinal) : string;
  351. const
  352. HexTbl : array[0..15] of char='0123456789ABCDEF';
  353. var
  354. i,j : cardinal;
  355. begin
  356. { calculate required length }
  357. i:=0;
  358. j:=val;
  359. while (j>0) do
  360. begin
  361. inc(i);
  362. j:=j shr 4;
  363. end;
  364. { generate fillers }
  365. j:=0;
  366. while (i+j<cnt) do
  367. begin
  368. inc(j);
  369. hexstr[j]:='0';
  370. end;
  371. { generate hex }
  372. inc(j,i);
  373. hexstr[0]:=chr(j);
  374. while (val>0) do
  375. begin
  376. hexstr[j]:=hextbl[val and $f];
  377. dec(j);
  378. val:=val shr 4;
  379. end;
  380. end;
  381. function DStr(l:longint):string;
  382. var
  383. TmpStr : string[32];
  384. i : longint;
  385. begin
  386. Str(l,TmpStr);
  387. i:=Length(TmpStr);
  388. while (i>3) do
  389. begin
  390. dec(i,3);
  391. if TmpStr[i]<>'-' then
  392. insert('.',TmpStr,i+1);
  393. end;
  394. DStr:=TmpStr;
  395. end;
  396. function trimbspace(const s:string):string;
  397. {
  398. return s with all leading spaces and tabs removed
  399. }
  400. var
  401. i,j : longint;
  402. begin
  403. j:=1;
  404. i:=length(s);
  405. while (j<i) and (s[j] in [#9,' ']) do
  406. inc(j);
  407. trimbspace:=Copy(s,j,i-j+1);
  408. end;
  409. function trimspace(const s:string):string;
  410. {
  411. return s with all leading and ending spaces and tabs removed
  412. }
  413. var
  414. i,j : longint;
  415. begin
  416. i:=length(s);
  417. while (i>0) and (s[i] in [#9,' ']) do
  418. dec(i);
  419. j:=1;
  420. while (j<i) and (s[j] in [#9,' ']) do
  421. inc(j);
  422. trimspace:=Copy(s,j,i-j+1);
  423. end;
  424. function space (b : longint): string;
  425. var
  426. s: string;
  427. begin
  428. space[0] := chr(b);
  429. s[0] := chr(b);
  430. FillChar (S[1],b,' ');
  431. space:=s;
  432. end;
  433. function PadSpace(const s:string;len:longint):string;
  434. {
  435. return s with spaces add to the end
  436. }
  437. begin
  438. if length(s)<len then
  439. PadSpace:=s+Space(len-length(s))
  440. else
  441. PadSpace:=s;
  442. end;
  443. function GetToken(var s:string;endchar:char):string;
  444. var
  445. i : longint;
  446. begin
  447. GetToken:='';
  448. s:=TrimSpace(s);
  449. if (length(s)>0) and
  450. (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. Ultra basic KISS Lzw (de)compressor
  941. *****************************************************************************}
  942. {This is an extremely basic implementation of the Lzw algorithm. It
  943. compresses 7-bit ASCII strings into 8-bit compressed strings.
  944. The Lzw dictionary is preinitialized with 0..127, therefore this
  945. part of the dictionary does not need to be stored in the arrays.
  946. The Lzw code size is allways 8 bit, so we do not need complex code
  947. that can write partial bytes.}
  948. function minilzw_encode(const s:string):string;
  949. var t,u,i:byte;
  950. c:char;
  951. data:array[128..255] of char;
  952. previous:array[128..255] of byte;
  953. lzwptr:byte;
  954. next_avail:set of 0..255;
  955. label l1;
  956. begin
  957. minilzw_encode:='';
  958. if s<>'' then
  959. begin
  960. lzwptr:=127;
  961. t:=byte(s[1]);
  962. i:=2;
  963. u:=128;
  964. next_avail:=[];
  965. while i<=length(s) do
  966. begin
  967. c:=s[i];
  968. if not(t in next_avail) or (u>lzwptr) then goto l1;
  969. while (previous[u]<>t) or (data[u]<>c) do
  970. begin
  971. inc(u);
  972. if u>lzwptr then goto l1;
  973. end;
  974. t:=u;
  975. inc(i);
  976. continue;
  977. l1:
  978. {It's a pity that we still need those awfull tricks
  979. with this modern compiler. Without this performance
  980. of the entire procedure drops about 3 times.}
  981. inc(minilzw_encode[0]);
  982. minilzw_encode[length(minilzw_encode)]:=char(t);
  983. if lzwptr=255 then
  984. begin
  985. lzwptr:=127;
  986. next_avail:=[];
  987. end
  988. else
  989. begin
  990. inc(lzwptr);
  991. data[lzwptr]:=c;
  992. previous[lzwptr]:=t;
  993. include(next_avail,t);
  994. end;
  995. t:=byte(c);
  996. u:=128;
  997. inc(i);
  998. end;
  999. inc(minilzw_encode[0]);
  1000. minilzw_encode[length(minilzw_encode)]:=char(t);
  1001. end;
  1002. end;
  1003. function minilzw_decode(const s:string):string;
  1004. var oldc,newc,c:char;
  1005. i,j:byte;
  1006. data:array[128..255] of char;
  1007. previous:array[128..255] of byte;
  1008. lzwptr:byte;
  1009. t:string;
  1010. begin
  1011. minilzw_decode:='';
  1012. if s<>'' then
  1013. begin
  1014. lzwptr:=127;
  1015. oldc:=s[1];
  1016. c:=oldc;
  1017. i:=2;
  1018. minilzw_decode:=oldc;
  1019. while i<=length(s) do
  1020. begin
  1021. newc:=s[i];
  1022. if byte(newc)>lzwptr then
  1023. begin
  1024. t:=c;
  1025. c:=oldc;
  1026. end
  1027. else
  1028. begin
  1029. c:=newc;
  1030. t:='';
  1031. end;
  1032. while c>=#128 do
  1033. begin
  1034. inc(t[0]);
  1035. t[length(t)]:=data[byte(c)];
  1036. byte(c):=previous[byte(c)];
  1037. end;
  1038. inc(minilzw_decode[0]);
  1039. minilzw_decode[length(minilzw_decode)]:=c;
  1040. for j:=length(t) downto 1 do
  1041. begin
  1042. inc(minilzw_decode[0]);
  1043. minilzw_decode[length(minilzw_decode)]:=t[j];
  1044. end;
  1045. if lzwptr=255 then
  1046. lzwptr:=127
  1047. else
  1048. begin
  1049. inc(lzwptr);
  1050. previous[lzwptr]:=byte(oldc);
  1051. data[lzwptr]:=c;
  1052. end;
  1053. oldc:=newc;
  1054. inc(i);
  1055. end;
  1056. end;
  1057. end;
  1058. procedure defaulterror(i:longint);
  1059. begin
  1060. writeln('Internal error ',i);
  1061. runerror(255);
  1062. end;
  1063. initialization
  1064. internalerrorproc:=@defaulterror;
  1065. makecrc32tbl;
  1066. initupperlower;
  1067. end.
  1068. {
  1069. $Log$
  1070. Revision 1.52 2005-04-23 14:15:58 hajny
  1071. * DeleteFile replaced with RemoveFile to avoid duplicate
  1072. Revision 1.51 2005/04/06 11:49:37 michael
  1073. * Fix methodpointer copy from callnode to loadnode
  1074. Revision 1.50 2005/03/04 16:49:22 peter
  1075. * getheapstatus fixes
  1076. Revision 1.49 2005/02/14 17:13:06 peter
  1077. * truncate log
  1078. Revision 1.48 2005/01/20 17:05:53 peter
  1079. * use val() for decoding integers
  1080. }