cutils.pas 33 KB

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