cutils.pas 33 KB

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