cutils.pas 19 KB

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