cutils.pas 32 KB

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