cutils.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854
  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. {$ifdef delphi}
  25. type
  26. dword = cardinal;
  27. qword = int64;
  28. {$endif}
  29. type
  30. pstring = ^string;
  31. {# Returns the minimal value between @var(a) and @var(b) }
  32. function min(a,b : longint) : longint;
  33. {# Returns the maximum value between @var(a) and @var(b) }
  34. function max(a,b : longint) : longint;
  35. {# Returns the value in @var(x) swapped to different endian }
  36. function SwapLong(x : longint): longint;
  37. {# Returns the value in @va(x) swapped to different endian }
  38. function SwapWord(x : word): word;
  39. {# Return value @var(i) aligned on @var(a) boundary }
  40. function align(i,a:longint):longint;
  41. function used_align(varalign,minalign,maxalign:longint):longint;
  42. function size_2_align(len : longint) : longint;
  43. procedure Replace(var s:string;s1:string;const s2:string);
  44. procedure ReplaceCase(var s:string;const s1,s2:string);
  45. function upper(const s : string) : string;
  46. function lower(const s : string) : string;
  47. function trimbspace(const s:string):string;
  48. function trimspace(const s:string):string;
  49. function space (b : longint): string;
  50. function PadSpace(const s:string;len:longint):string;
  51. function GetToken(var s:string;endchar:char):string;
  52. procedure uppervar(var s : string);
  53. function hexstr(val : cardinal;cnt : cardinal) : string;
  54. function tostru(i:cardinal) : string;
  55. function tostr(i : longint) : string;
  56. function int64tostr(i : int64) : string;
  57. function tostr_with_plus(i : longint) : string;
  58. function DStr(l:longint):string;
  59. procedure valint(S : string;var V : longint;var code : integer);
  60. {# Returns true if the string s is a number }
  61. function is_number(const s : string) : boolean;
  62. {# Returns true if value is a power of 2, the actual
  63. exponent value is returned in power.
  64. }
  65. function ispowerof2(value : int64;var power : longint) : boolean;
  66. function maybequoted(const s:string):string;
  67. function CompareText(S1, S2: string): longint;
  68. { releases the string p and assignes nil to p }
  69. { if p=nil then freemem isn't called }
  70. procedure stringdispose(var p : pstring);
  71. { allocates mem for a copy of s, copies s to this mem and returns }
  72. { a pointer to this mem }
  73. function stringdup(const s : string) : pstring;
  74. {# Allocates memory for the string @var(s) and copies s as zero
  75. terminated string to that allocated memory and returns a pointer
  76. to that mem
  77. }
  78. function strpnew(const s : string) : pchar;
  79. procedure strdispose(var p : pchar);
  80. {# makes the character @var(c) lowercase, with spanish, french and german
  81. character set
  82. }
  83. function lowercase(c : char) : char;
  84. { makes zero terminated string to a pascal string }
  85. { the data in p is modified and p is returned }
  86. function pchar2pstring(p : pchar) : pstring;
  87. { ambivalent to pchar2pstring }
  88. function pstring2pchar(p : pstring) : pchar;
  89. { Speed/Hash value }
  90. Function GetSpeedValue(Const s:String):cardinal;
  91. { Ansistring (pchar+length) support }
  92. procedure ansistringdispose(var p : pchar;length : longint);
  93. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  94. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  95. {*****************************************************************************
  96. File Functions
  97. *****************************************************************************}
  98. function DeleteFile(const fn:string):boolean;
  99. implementation
  100. uses
  101. {$ifdef delphi}
  102. sysutils
  103. {$else}
  104. strings
  105. {$endif}
  106. ;
  107. var
  108. uppertbl,
  109. lowertbl : array[char] of char;
  110. function min(a,b : longint) : longint;
  111. {
  112. return the minimal of a and b
  113. }
  114. begin
  115. if a>b then
  116. min:=b
  117. else
  118. min:=a;
  119. end;
  120. function max(a,b : longint) : longint;
  121. {
  122. return the maximum of a and b
  123. }
  124. begin
  125. if a<b then
  126. max:=b
  127. else
  128. max:=a;
  129. end;
  130. Function SwapLong(x : longint): longint;
  131. var
  132. y : word;
  133. z : word;
  134. Begin
  135. y := (x shr 16) and $FFFF;
  136. y := ((y shl 8) and $FFFF) or ((y shr 8) and $ff);
  137. z := x and $FFFF;
  138. z := ((z shl 8) and $FFFF) or ((z shr 8) and $ff);
  139. SwapLong := (longint(z) shl 16) or longint(y);
  140. End;
  141. Function SwapWord(x : word): word;
  142. var
  143. z : byte;
  144. Begin
  145. z := (x shr 8) and $ff;
  146. x := x and $ff;
  147. x := (x shl 8);
  148. SwapWord := x or z;
  149. End;
  150. function align(i,a:longint):longint;
  151. {
  152. return value <i> aligned <a> boundary
  153. }
  154. begin
  155. { for 0 and 1 no aligning is needed }
  156. if a<=1 then
  157. align:=i
  158. else
  159. align:=((i+a-1) div a) * a;
  160. end;
  161. function size_2_align(len : longint) : longint;
  162. begin
  163. if len>16 then
  164. size_2_align:=32
  165. else if len>8 then
  166. size_2_align:=16
  167. else if len>4 then
  168. size_2_align:=8
  169. else if len>2 then
  170. size_2_align:=4
  171. else if len>1 then
  172. size_2_align:=2
  173. else
  174. size_2_align:=1;
  175. end;
  176. function used_align(varalign,minalign,maxalign:longint):longint;
  177. begin
  178. { varalign : minimum alignment required for the variable
  179. minalign : Minimum alignment of this structure, 0 = undefined
  180. maxalign : Maximum alignment of this structure, 0 = undefined }
  181. if (minalign>0) and
  182. (varalign<minalign) then
  183. used_align:=minalign
  184. else
  185. begin
  186. if (maxalign>0) and
  187. (varalign>maxalign) then
  188. used_align:=maxalign
  189. else
  190. used_align:=varalign;
  191. end;
  192. end;
  193. procedure Replace(var s:string;s1:string;const s2:string);
  194. var
  195. last,
  196. i : longint;
  197. begin
  198. s1:=upper(s1);
  199. last:=0;
  200. repeat
  201. i:=pos(s1,upper(s));
  202. if i=last then
  203. i:=0;
  204. if (i>0) then
  205. begin
  206. Delete(s,i,length(s1));
  207. Insert(s2,s,i);
  208. last:=i;
  209. end;
  210. until (i=0);
  211. end;
  212. procedure ReplaceCase(var s:string;const s1,s2:string);
  213. var
  214. last,
  215. i : longint;
  216. begin
  217. last:=0;
  218. repeat
  219. i:=pos(s1,s);
  220. if i=last then
  221. i:=0;
  222. if (i>0) then
  223. begin
  224. Delete(s,i,length(s1));
  225. Insert(s2,s,i);
  226. last:=i;
  227. end;
  228. until (i=0);
  229. end;
  230. function upper(const s : string) : string;
  231. {
  232. return uppercased string of s
  233. }
  234. var
  235. i : longint;
  236. begin
  237. for i:=1 to length(s) do
  238. upper[i]:=uppertbl[s[i]];
  239. upper[0]:=s[0];
  240. end;
  241. function lower(const s : string) : string;
  242. {
  243. return lowercased string of s
  244. }
  245. var
  246. i : longint;
  247. begin
  248. for i:=1 to length(s) do
  249. lower[i]:=lowertbl[s[i]];
  250. lower[0]:=s[0];
  251. end;
  252. procedure uppervar(var s : string);
  253. {
  254. uppercase string s
  255. }
  256. var
  257. i : longint;
  258. begin
  259. for i:=1 to length(s) do
  260. s[i]:=uppertbl[s[i]];
  261. end;
  262. procedure initupperlower;
  263. var
  264. c : char;
  265. begin
  266. for c:=#0 to #255 do
  267. begin
  268. lowertbl[c]:=c;
  269. uppertbl[c]:=c;
  270. case c of
  271. 'A'..'Z' :
  272. lowertbl[c]:=char(byte(c)+32);
  273. 'a'..'z' :
  274. uppertbl[c]:=char(byte(c)-32);
  275. end;
  276. end;
  277. end;
  278. function hexstr(val : cardinal;cnt : cardinal) : string;
  279. const
  280. HexTbl : array[0..15] of char='0123456789ABCDEF';
  281. var
  282. i,j : cardinal;
  283. begin
  284. { calculate required length }
  285. i:=0;
  286. j:=val;
  287. while (j>0) do
  288. begin
  289. inc(i);
  290. j:=j shr 4;
  291. end;
  292. { generate fillers }
  293. j:=0;
  294. while (i+j<cnt) do
  295. begin
  296. inc(j);
  297. hexstr[j]:='0';
  298. end;
  299. { generate hex }
  300. inc(j,i);
  301. hexstr[0]:=chr(j);
  302. while (val>0) do
  303. begin
  304. hexstr[j]:=hextbl[val and $f];
  305. dec(j);
  306. val:=val shr 4;
  307. end;
  308. end;
  309. function tostru(i:cardinal):string;
  310. {
  311. return string of value i, but for cardinals
  312. }
  313. var
  314. hs : string;
  315. begin
  316. str(i,hs);
  317. tostru:=hs;
  318. end;
  319. function DStr(l:longint):string;
  320. var
  321. TmpStr : string[32];
  322. i : longint;
  323. begin
  324. Str(l,TmpStr);
  325. i:=Length(TmpStr);
  326. while (i>3) do
  327. begin
  328. dec(i,3);
  329. if TmpStr[i]<>'-' then
  330. insert('.',TmpStr,i+1);
  331. end;
  332. DStr:=TmpStr;
  333. end;
  334. function trimbspace(const s:string):string;
  335. {
  336. return s with all leading spaces and tabs removed
  337. }
  338. var
  339. i,j : longint;
  340. begin
  341. j:=1;
  342. i:=length(s);
  343. while (j<i) and (s[j] in [#9,' ']) do
  344. inc(j);
  345. trimbspace:=Copy(s,j,i-j+1);
  346. end;
  347. function trimspace(const s:string):string;
  348. {
  349. return s with all leading and ending spaces and tabs removed
  350. }
  351. var
  352. i,j : longint;
  353. begin
  354. i:=length(s);
  355. while (i>0) and (s[i] in [#9,' ']) do
  356. dec(i);
  357. j:=1;
  358. while (j<i) and (s[j] in [#9,' ']) do
  359. inc(j);
  360. trimspace:=Copy(s,j,i-j+1);
  361. end;
  362. function space (b : longint): string;
  363. begin
  364. space[0] := chr(b);
  365. FillChar (Space[1],b,' ');
  366. end;
  367. function PadSpace(const s:string;len:longint):string;
  368. {
  369. return s with spaces add to the end
  370. }
  371. begin
  372. if length(s)<len then
  373. PadSpace:=s+Space(len-length(s))
  374. else
  375. PadSpace:=s;
  376. end;
  377. function GetToken(var s:string;endchar:char):string;
  378. var
  379. i : longint;
  380. begin
  381. s:=TrimSpace(s);
  382. i:=pos(EndChar,s);
  383. if i=0 then
  384. begin
  385. GetToken:=s;
  386. s:='';
  387. end
  388. else
  389. begin
  390. GetToken:=Copy(s,1,i-1);
  391. Delete(s,1,i);
  392. end;
  393. end;
  394. function tostr(i : longint) : string;
  395. {
  396. return string of value i
  397. }
  398. var
  399. hs : string;
  400. begin
  401. str(i,result);
  402. end;
  403. function int64tostr(i : int64) : string;
  404. {
  405. return string of value i
  406. }
  407. var
  408. hs : string;
  409. begin
  410. str(i,hs);
  411. int64tostr:=hs;
  412. end;
  413. function tostr_with_plus(i : longint) : string;
  414. {
  415. return string of value i, but always include a + when i>=0
  416. }
  417. var
  418. hs : string;
  419. begin
  420. str(i,hs);
  421. if i>=0 then
  422. tostr_with_plus:='+'+hs
  423. else
  424. tostr_with_plus:=hs;
  425. end;
  426. procedure valint(S : string;var V : longint;var code : integer);
  427. {
  428. val() with support for octal, which is not supported under tp7
  429. }
  430. {$ifndef FPC}
  431. var
  432. vs : longint;
  433. c : byte;
  434. begin
  435. if s[1]='%' then
  436. begin
  437. vs:=0;
  438. longint(v):=0;
  439. for c:=2 to length(s) do
  440. begin
  441. if s[c]='0' then
  442. vs:=vs shl 1
  443. else
  444. if s[c]='1' then
  445. vs:=vs shl 1+1
  446. else
  447. begin
  448. code:=c;
  449. exit;
  450. end;
  451. end;
  452. code:=0;
  453. longint(v):=vs;
  454. end
  455. else
  456. system.val(S,V,code);
  457. end;
  458. {$else not FPC}
  459. begin
  460. system.val(S,V,code);
  461. end;
  462. {$endif not FPC}
  463. function is_number(const s : string) : boolean;
  464. {
  465. is string a correct number ?
  466. }
  467. var
  468. w : integer;
  469. l : longint;
  470. begin
  471. valint(s,l,w);
  472. is_number:=(w=0);
  473. end;
  474. function ispowerof2(value : int64;var power : longint) : boolean;
  475. {
  476. return if value is a power of 2. And if correct return the power
  477. }
  478. var
  479. hl : int64;
  480. i : longint;
  481. begin
  482. if value and (value - 1) <> 0 then
  483. begin
  484. ispowerof2 := false;
  485. exit
  486. end;
  487. hl:=1;
  488. ispowerof2:=true;
  489. for i:=0 to 63 do
  490. begin
  491. if hl=value then
  492. begin
  493. power:=i;
  494. exit;
  495. end;
  496. hl:=hl shl 1;
  497. end;
  498. ispowerof2:=false;
  499. end;
  500. function maybequoted(const s:string):string;
  501. var
  502. s1 : string;
  503. i : integer;
  504. begin
  505. if (pos('"',s)>0) then
  506. begin
  507. s1:='"';
  508. for i:=1 to length(s) do
  509. begin
  510. if s[i]='"' then
  511. s1:=s1+'\"'
  512. else
  513. s1:=s1+s[i];
  514. end;
  515. maybequoted:=s1+'"';
  516. end
  517. else if (pos(' ',s)>0) then
  518. maybequoted:='"'+s+'"'
  519. else
  520. maybequoted:=s;
  521. end;
  522. function pchar2pstring(p : pchar) : pstring;
  523. var
  524. w,i : longint;
  525. begin
  526. w:=strlen(p);
  527. for i:=w-1 downto 0 do
  528. p[i+1]:=p[i];
  529. p[0]:=chr(w);
  530. pchar2pstring:=pstring(p);
  531. end;
  532. function pstring2pchar(p : pstring) : pchar;
  533. var
  534. w,i : longint;
  535. begin
  536. w:=length(p^);
  537. for i:=1 to w do
  538. p^[i-1]:=p^[i];
  539. p^[w]:=#0;
  540. pstring2pchar:=pchar(p);
  541. end;
  542. function lowercase(c : char) : char;
  543. begin
  544. case c of
  545. #65..#90 : c := chr(ord (c) + 32);
  546. #154 : c:=#129; { german }
  547. #142 : c:=#132; { german }
  548. #153 : c:=#148; { german }
  549. #144 : c:=#130; { french }
  550. #128 : c:=#135; { french }
  551. #143 : c:=#134; { swedish/norge (?) }
  552. #165 : c:=#164; { spanish }
  553. #228 : c:=#229; { greek }
  554. #226 : c:=#231; { greek }
  555. #232 : c:=#227; { greek }
  556. end;
  557. lowercase := c;
  558. end;
  559. function strpnew(const s : string) : pchar;
  560. var
  561. p : pchar;
  562. begin
  563. getmem(p,length(s)+1);
  564. strpcopy(p,s);
  565. strpnew:=p;
  566. end;
  567. procedure strdispose(var p : pchar);
  568. begin
  569. if assigned(p) then
  570. begin
  571. freemem(p,strlen(p)+1);
  572. p:=nil;
  573. end;
  574. end;
  575. procedure stringdispose(var p : pstring);
  576. begin
  577. if assigned(p) then
  578. freemem(p,length(p^)+1);
  579. p:=nil;
  580. end;
  581. function stringdup(const s : string) : pstring;
  582. var
  583. p : pstring;
  584. begin
  585. getmem(p,length(s)+1);
  586. p^:=s;
  587. stringdup:=p;
  588. end;
  589. function CompareText(S1, S2: string): longint;
  590. begin
  591. UpperVar(S1);
  592. UpperVar(S2);
  593. if S1<S2 then
  594. CompareText:=-1
  595. else
  596. if S1>S2 then
  597. CompareText:= 1
  598. else
  599. CompareText:=0;
  600. end;
  601. {*****************************************************************************
  602. GetSpeedValue
  603. *****************************************************************************}
  604. {$ifdef ver1_0}
  605. {$R-}
  606. {$endif}
  607. var
  608. Crc32Tbl : array[0..255] of cardinal;
  609. procedure MakeCRC32Tbl;
  610. var
  611. crc : cardinal;
  612. i,n : integer;
  613. begin
  614. for i:=0 to 255 do
  615. begin
  616. crc:=i;
  617. for n:=1 to 8 do
  618. if odd(longint(crc)) then
  619. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  620. else
  621. crc:=cardinal(crc shr 1);
  622. Crc32Tbl[i]:=crc;
  623. end;
  624. end;
  625. Function GetSpeedValue(Const s:String):cardinal;
  626. var
  627. i : integer;
  628. InitCrc : cardinal;
  629. begin
  630. if Crc32Tbl[1]=0 then
  631. MakeCrc32Tbl;
  632. InitCrc:=cardinal($ffffffff);
  633. for i:=1 to Length(s) do
  634. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  635. GetSpeedValue:=InitCrc;
  636. end;
  637. {*****************************************************************************
  638. Ansistring (PChar+Length)
  639. *****************************************************************************}
  640. procedure ansistringdispose(var p : pchar;length : longint);
  641. begin
  642. if assigned(p) then
  643. freemem(p,length+1);
  644. p:=nil;
  645. end;
  646. { enable ansistring comparison }
  647. { 0 means equal }
  648. { 1 means p1 > p2 }
  649. { -1 means p1 < p2 }
  650. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  651. var
  652. i,j : longint;
  653. begin
  654. compareansistrings:=0;
  655. j:=min(length1,length2);
  656. i:=0;
  657. while (i<j) do
  658. begin
  659. if p1[i]>p2[i] then
  660. begin
  661. compareansistrings:=1;
  662. exit;
  663. end
  664. else
  665. if p1[i]<p2[i] then
  666. begin
  667. compareansistrings:=-1;
  668. exit;
  669. end;
  670. inc(i);
  671. end;
  672. if length1>length2 then
  673. compareansistrings:=1
  674. else
  675. if length1<length2 then
  676. compareansistrings:=-1;
  677. end;
  678. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  679. var
  680. p : pchar;
  681. begin
  682. getmem(p,length1+length2+1);
  683. move(p1[0],p[0],length1);
  684. move(p2[0],p[length1],length2+1);
  685. concatansistrings:=p;
  686. end;
  687. {*****************************************************************************
  688. File Functions
  689. *****************************************************************************}
  690. function DeleteFile(const fn:string):boolean;
  691. var
  692. f : file;
  693. begin
  694. {$I-}
  695. assign(f,fn);
  696. erase(f);
  697. {$I-}
  698. DeleteFile:=(IOResult=0);
  699. end;
  700. initialization
  701. initupperlower;
  702. end.
  703. {
  704. $Log$
  705. Revision 1.22 2002-09-05 19:29:42 peter
  706. * memdebug enhancements
  707. Revision 1.21 2002/07/26 11:16:35 jonas
  708. * fixed (actual and potential) range errors
  709. Revision 1.20 2002/07/07 11:13:34 carl
  710. * range check error fix (patch from Sergey)
  711. Revision 1.19 2002/07/07 09:52:32 florian
  712. * powerpc target fixed, very simple units can be compiled
  713. * some basic stuff for better callparanode handling, far from being finished
  714. Revision 1.18 2002/07/01 18:46:22 peter
  715. * internal linker
  716. * reorganized aasm layer
  717. Revision 1.17 2002/05/18 13:34:07 peter
  718. * readded missing revisions
  719. Revision 1.16 2002/05/16 19:46:36 carl
  720. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  721. + try to fix temp allocation (still in ifdef)
  722. + generic constructor calls
  723. + start of tassembler / tmodulebase class cleanup
  724. Revision 1.14 2002/04/12 17:16:35 carl
  725. + more documentation of basic unit
  726. }