cutils.pas 32 KB

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