cutils.pas 18 KB

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