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