cutils.pas 33 KB

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