cutils.pas 31 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200
  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] in qchars then
  536. backspace_quote:=backspace_quote+'\';
  537. backspace_quote:=backspace_quote+s[i];
  538. end;
  539. end;
  540. function maybequoted(const s:string):string;
  541. var
  542. s1 : string;
  543. i : integer;
  544. quoted : boolean;
  545. begin
  546. quoted:=false;
  547. s1:='"';
  548. for i:=1 to length(s) do
  549. begin
  550. case s[i] of
  551. '"' :
  552. begin
  553. quoted:=true;
  554. s1:=s1+'\"';
  555. end;
  556. ' ',
  557. #128..#255 :
  558. begin
  559. quoted:=true;
  560. s1:=s1+s[i];
  561. end;
  562. else
  563. s1:=s1+s[i];
  564. end;
  565. end;
  566. if quoted then
  567. maybequoted:=s1+'"'
  568. else
  569. maybequoted:=s;
  570. end;
  571. function pchar2pstring(p : pchar) : pstring;
  572. var
  573. w,i : longint;
  574. begin
  575. w:=strlen(p);
  576. for i:=w-1 downto 0 do
  577. p[i+1]:=p[i];
  578. p[0]:=chr(w);
  579. pchar2pstring:=pstring(p);
  580. end;
  581. function pstring2pchar(p : pstring) : pchar;
  582. var
  583. w,i : longint;
  584. begin
  585. w:=length(p^);
  586. for i:=1 to w do
  587. p^[i-1]:=p^[i];
  588. p^[w]:=#0;
  589. pstring2pchar:=pchar(p);
  590. end;
  591. function lowercase(c : char) : char;
  592. begin
  593. case c of
  594. #65..#90 : c := chr(ord (c) + 32);
  595. #154 : c:=#129; { german }
  596. #142 : c:=#132; { german }
  597. #153 : c:=#148; { german }
  598. #144 : c:=#130; { french }
  599. #128 : c:=#135; { french }
  600. #143 : c:=#134; { swedish/norge (?) }
  601. #165 : c:=#164; { spanish }
  602. #228 : c:=#229; { greek }
  603. #226 : c:=#231; { greek }
  604. #232 : c:=#227; { greek }
  605. end;
  606. lowercase := c;
  607. end;
  608. function strpnew(const s : string) : pchar;
  609. var
  610. p : pchar;
  611. begin
  612. getmem(p,length(s)+1);
  613. strpcopy(p,s);
  614. strpnew:=p;
  615. end;
  616. procedure strdispose(var p : pchar);
  617. begin
  618. if assigned(p) then
  619. begin
  620. freemem(p,strlen(p)+1);
  621. p:=nil;
  622. end;
  623. end;
  624. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  625. begin
  626. if assigned(p) then
  627. begin
  628. freemem(p,length(p^)+1);
  629. p:=nil;
  630. end;
  631. end;
  632. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  633. begin
  634. getmem(result,length(s)+1);
  635. result^:=s;
  636. end;
  637. function CompareText(S1, S2: string): longint;
  638. begin
  639. UpperVar(S1);
  640. UpperVar(S2);
  641. if S1<S2 then
  642. CompareText:=-1
  643. else
  644. if S1>S2 then
  645. CompareText:= 1
  646. else
  647. CompareText:=0;
  648. end;
  649. function string_evaluate(s:string;get_var_value:get_var_value_proc;
  650. const vars:array of string):Pchar;
  651. {S contains a prototype of a stabstring. Stabstr_evaluate will expand
  652. variables and parameters.
  653. Output is s in ASCIIZ format, with the following expanded:
  654. ${varname} - The variable name is expanded.
  655. $n - The parameter n is expanded.
  656. $$ - Is expanded to $
  657. }
  658. const maxvalue=9;
  659. maxdata=1023;
  660. var i,j:byte;
  661. varname:string[63];
  662. varno,varcounter:byte;
  663. varvalues:array[0..9] of Pstring;
  664. {1 kb of parameters is the limit. 256 extra bytes are allocated to
  665. ensure buffer integrity.}
  666. varvaluedata:array[0..maxdata+256] of char;
  667. varptr:Pchar;
  668. len:cardinal;
  669. r:Pchar;
  670. begin
  671. {Two pass approach, first, calculate the length and receive variables.}
  672. i:=1;
  673. len:=0;
  674. varcounter:=0;
  675. varptr:=@varvaluedata;
  676. while i<=length(s) do
  677. begin
  678. if (s[i]='$') and (i<length(s)) then
  679. begin
  680. if s[i+1]='$' then
  681. begin
  682. inc(len);
  683. inc(i);
  684. end
  685. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  686. begin
  687. varname:='';
  688. inc(i,2);
  689. repeat
  690. inc(varname[0]);
  691. varname[length(varname)]:=s[i];
  692. s[i]:=char(varcounter);
  693. inc(i);
  694. until s[i]='}';
  695. varvalues[varcounter]:=Pstring(varptr);
  696. if varptr>@varvaluedata+maxdata then
  697. runerror($8001); {No internalerror available}
  698. Pstring(varptr)^:=get_var_value(varname);
  699. inc(len,length(Pstring(varptr)^));
  700. inc(varptr,length(Pstring(varptr)^)+1);
  701. inc(varcounter);
  702. end
  703. else if s[i+1] in ['0'..'9'] then
  704. begin
  705. inc(len,length(vars[byte(s[i+1])-byte('1')]));
  706. inc(i);
  707. end;
  708. end
  709. else
  710. inc(len);
  711. inc(i);
  712. end;
  713. {Second pass, writeout stabstring.}
  714. getmem(r,len+1);
  715. string_evaluate:=r;
  716. i:=1;
  717. while i<=length(s) do
  718. begin
  719. if (s[i]='$') and (i<length(s)) then
  720. begin
  721. if s[i+1]='$' then
  722. begin
  723. r^:='$';
  724. inc(r);
  725. inc(i);
  726. end
  727. else if (s[i+1]='{') and (length(s)>2) and (i<length(s)-2) then
  728. begin
  729. varname:='';
  730. inc(i,2);
  731. varno:=byte(s[i]);
  732. repeat
  733. inc(i);
  734. until s[i]='}';
  735. for j:=1 to length(varvalues[varno]^) do
  736. begin
  737. r^:=varvalues[varno]^[j];
  738. inc(r);
  739. end;
  740. end
  741. else if s[i+1] in ['0'..'9'] then
  742. begin
  743. for j:=1 to length(vars[byte(s[i+1])-byte('1')]) do
  744. begin
  745. r^:=vars[byte(s[i+1])-byte('1')][j];
  746. inc(r);
  747. end;
  748. inc(i);
  749. end
  750. end
  751. else
  752. begin
  753. r^:=s[i];
  754. inc(r);
  755. end;
  756. inc(i);
  757. end;
  758. r^:=#0;
  759. end;
  760. {*****************************************************************************
  761. GetSpeedValue
  762. *****************************************************************************}
  763. {$ifdef ver1_0}
  764. {$R-}
  765. {$endif}
  766. var
  767. Crc32Tbl : array[0..255] of cardinal;
  768. procedure MakeCRC32Tbl;
  769. var
  770. crc : cardinal;
  771. i,n : integer;
  772. begin
  773. for i:=0 to 255 do
  774. begin
  775. crc:=i;
  776. for n:=1 to 8 do
  777. if odd(longint(crc)) then
  778. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  779. else
  780. crc:=cardinal(crc shr 1);
  781. Crc32Tbl[i]:=crc;
  782. end;
  783. end;
  784. Function GetSpeedValue(Const s:String):cardinal;
  785. var
  786. i : integer;
  787. InitCrc : cardinal;
  788. begin
  789. InitCrc:=cardinal($ffffffff);
  790. for i:=1 to Length(s) do
  791. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  792. GetSpeedValue:=InitCrc;
  793. end;
  794. {*****************************************************************************
  795. Ansistring (PChar+Length)
  796. *****************************************************************************}
  797. procedure ansistringdispose(var p : pchar;length : longint);
  798. begin
  799. if assigned(p) then
  800. begin
  801. freemem(p,length+1);
  802. p:=nil;
  803. end;
  804. end;
  805. { enable ansistring comparison }
  806. { 0 means equal }
  807. { 1 means p1 > p2 }
  808. { -1 means p1 < p2 }
  809. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  810. var
  811. i,j : longint;
  812. begin
  813. compareansistrings:=0;
  814. j:=min(length1,length2);
  815. i:=0;
  816. while (i<j) do
  817. begin
  818. if p1[i]>p2[i] then
  819. begin
  820. compareansistrings:=1;
  821. exit;
  822. end
  823. else
  824. if p1[i]<p2[i] then
  825. begin
  826. compareansistrings:=-1;
  827. exit;
  828. end;
  829. inc(i);
  830. end;
  831. if length1>length2 then
  832. compareansistrings:=1
  833. else
  834. if length1<length2 then
  835. compareansistrings:=-1;
  836. end;
  837. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  838. var
  839. p : pchar;
  840. begin
  841. getmem(p,length1+length2+1);
  842. move(p1[0],p[0],length1);
  843. move(p2[0],p[length1],length2+1);
  844. concatansistrings:=p;
  845. end;
  846. {*****************************************************************************
  847. File Functions
  848. *****************************************************************************}
  849. function DeleteFile(const fn:string):boolean;
  850. var
  851. f : file;
  852. begin
  853. {$I-}
  854. assign(f,fn);
  855. erase(f);
  856. {$I-}
  857. DeleteFile:=(IOResult=0);
  858. end;
  859. {*****************************************************************************
  860. Ultra basic KISS Lzw (de)compressor
  861. *****************************************************************************}
  862. {This is an extremely basic implementation of the Lzw algorithm. It
  863. compresses 7-bit ASCII strings into 8-bit compressed strings.
  864. The Lzw dictionary is preinitialized with 0..127, therefore this
  865. part of the dictionary does not need to be stored in the arrays.
  866. The Lzw code size is allways 8 bit, so we do not need complex code
  867. that can write partial bytes.}
  868. function minilzw_encode(const s:string):string;
  869. var t,u,i:byte;
  870. c:char;
  871. data:array[128..255] of char;
  872. previous:array[128..255] of byte;
  873. lzwptr:byte;
  874. next_avail:set of 0..255;
  875. label l1;
  876. begin
  877. minilzw_encode:='';
  878. if s<>'' then
  879. begin
  880. lzwptr:=127;
  881. t:=byte(s[1]);
  882. i:=2;
  883. u:=128;
  884. next_avail:=[];
  885. while i<=length(s) do
  886. begin
  887. c:=s[i];
  888. if not(t in next_avail) or (u>lzwptr) then goto l1;
  889. while (previous[u]<>t) or (data[u]<>c) do
  890. begin
  891. inc(u);
  892. if u>lzwptr then goto l1;
  893. end;
  894. t:=u;
  895. inc(i);
  896. continue;
  897. l1:
  898. {It's a pity that we still need those awfull tricks
  899. with this modern compiler. Without this performance
  900. of the entire procedure drops about 3 times.}
  901. inc(minilzw_encode[0]);
  902. minilzw_encode[length(minilzw_encode)]:=char(t);
  903. if lzwptr=255 then
  904. begin
  905. lzwptr:=127;
  906. next_avail:=[];
  907. end
  908. else
  909. begin
  910. inc(lzwptr);
  911. data[lzwptr]:=c;
  912. previous[lzwptr]:=t;
  913. include(next_avail,t);
  914. end;
  915. t:=byte(c);
  916. u:=128;
  917. inc(i);
  918. end;
  919. inc(minilzw_encode[0]);
  920. minilzw_encode[length(minilzw_encode)]:=char(t);
  921. end;
  922. end;
  923. function minilzw_decode(const s:string):string;
  924. var oldc,newc,c:char;
  925. i,j:byte;
  926. data:array[128..255] of char;
  927. previous:array[128..255] of byte;
  928. lzwptr:byte;
  929. t:string;
  930. begin
  931. minilzw_decode:='';
  932. if s<>'' then
  933. begin
  934. lzwptr:=127;
  935. oldc:=s[1];
  936. c:=oldc;
  937. i:=2;
  938. minilzw_decode:=oldc;
  939. while i<=length(s) do
  940. begin
  941. newc:=s[i];
  942. if byte(newc)>lzwptr then
  943. begin
  944. t:=c;
  945. c:=oldc;
  946. end
  947. else
  948. begin
  949. c:=newc;
  950. t:='';
  951. end;
  952. while c>=#128 do
  953. begin
  954. inc(t[0]);
  955. t[length(t)]:=data[byte(c)];
  956. byte(c):=previous[byte(c)];
  957. end;
  958. inc(minilzw_decode[0]);
  959. minilzw_decode[length(minilzw_decode)]:=c;
  960. for j:=length(t) downto 1 do
  961. begin
  962. inc(minilzw_decode[0]);
  963. minilzw_decode[length(minilzw_decode)]:=t[j];
  964. end;
  965. if lzwptr=255 then
  966. lzwptr:=127
  967. else
  968. begin
  969. inc(lzwptr);
  970. previous[lzwptr]:=byte(oldc);
  971. data[lzwptr]:=c;
  972. end;
  973. oldc:=newc;
  974. inc(i);
  975. end;
  976. end;
  977. end;
  978. initialization
  979. makecrc32tbl;
  980. initupperlower;
  981. end.
  982. {
  983. $Log$
  984. Revision 1.34 2004-01-26 22:08:20 daniel
  985. * Bugfix on constant strings stab generation. Never worked and still
  986. doesn't work for unknown reasons.
  987. Revision 1.33 2004/01/25 13:18:59 daniel
  988. * Made varags parameter constant
  989. Revision 1.32 2004/01/25 11:33:48 daniel
  990. * 2nd round of gdb cleanup
  991. Revision 1.31 2004/01/15 15:16:18 daniel
  992. * Some minor stuff
  993. * Managed to eliminate speed effects of string compression
  994. Revision 1.30 2004/01/11 23:56:19 daniel
  995. * Experiment: Compress strings to save memory
  996. Did not save a single byte of mem; clearly the core size is boosted by
  997. temporary memory usage...
  998. Revision 1.29 2003/10/31 15:51:11 peter
  999. * USEINLINE directive added (not enabled yet)
  1000. Revision 1.28 2003/09/03 15:55:00 peter
  1001. * NEWRA branch merged
  1002. Revision 1.27.2.2 2003/08/29 17:28:59 peter
  1003. * next batch of updates
  1004. Revision 1.27.2.1 2003/08/29 09:41:25 daniel
  1005. * Further mkx86reg development
  1006. Revision 1.27 2003/07/05 20:06:28 jonas
  1007. * fixed some range check errors that occurred on big endian systems
  1008. * slightly optimized the swap*() functions
  1009. Revision 1.26 2003/04/04 15:34:25 peter
  1010. * quote names with hi-ascii chars
  1011. Revision 1.25 2003/01/09 21:42:27 peter
  1012. * realtostr added
  1013. Revision 1.24 2002/12/27 18:05:27 peter
  1014. * support quotes in gettoken
  1015. Revision 1.23 2002/10/05 12:43:24 carl
  1016. * fixes for Delphi 6 compilation
  1017. (warning : Some features do not work under Delphi)
  1018. Revision 1.22 2002/09/05 19:29:42 peter
  1019. * memdebug enhancements
  1020. Revision 1.21 2002/07/26 11:16:35 jonas
  1021. * fixed (actual and potential) range errors
  1022. Revision 1.20 2002/07/07 11:13:34 carl
  1023. * range check error fix (patch from Sergey)
  1024. Revision 1.19 2002/07/07 09:52:32 florian
  1025. * powerpc target fixed, very simple units can be compiled
  1026. * some basic stuff for better callparanode handling, far from being finished
  1027. Revision 1.18 2002/07/01 18:46:22 peter
  1028. * internal linker
  1029. * reorganized aasm layer
  1030. Revision 1.17 2002/05/18 13:34:07 peter
  1031. * readded missing revisions
  1032. Revision 1.16 2002/05/16 19:46:36 carl
  1033. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  1034. + try to fix temp allocation (still in ifdef)
  1035. + generic constructor calls
  1036. + start of tassembler / tmodulebase class cleanup
  1037. Revision 1.14 2002/04/12 17:16:35 carl
  1038. + more documentation of basic unit
  1039. }