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