cutils.pas 32 KB

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