cutils.pas 31 KB

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