cutils.pas 33 KB

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