cutils.pas 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152
  1. {
  2. Copyright (c) 1998-2002 by Florian Klaempfl
  3. This unit implements some support functions
  4. This program is free software; you can redistribute it and/or modify
  5. it under the terms of the GNU General Public License as published
  6. by the Free Software Foundation; either version 2 of the License, or
  7. (at your option) any later version.
  8. This program is distributed in the hope that it will be useful,
  9. but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. GNU General Public License for more details.
  12. You should have received a copy of the GNU General Public License
  13. along with this program; if not, write to the Free Software
  14. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  15. ****************************************************************************
  16. }
  17. {# This unit contains some generic support functions which are used
  18. in the different parts of the compiler.
  19. }
  20. unit cutils;
  21. {$i fpcdefs.inc}
  22. interface
  23. type
  24. pstring = ^string;
  25. Tcharset=set of char;
  26. var
  27. internalerrorproc : procedure(i:longint);
  28. {# Returns the minimal value between @var(a) and @var(b) }
  29. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  30. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  31. {# Returns the maximum value between @var(a) and @var(b) }
  32. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  33. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  34. {# Returns the value in @var(x) swapped to different endian }
  35. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  36. {# Returns the value in @var(x) swapped to different endian }
  37. function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  38. {# Returns the value in @va(x) swapped to different endian }
  39. function SwapWord(x : word): word;{$ifdef USEINLINE}inline;{$endif}
  40. {# Returns the value in @va(x) swapped to different endian }
  41. Function SwapQWord(x : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  42. {# Return value @var(i) aligned on @var(a) boundary }
  43. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  44. function used_align(varalign,minalign,maxalign:shortint):shortint;
  45. function size_2_align(len : longint) : shortint;
  46. procedure Replace(var s:string;s1:string;const s2:string);
  47. procedure Replace(var s:AnsiString;s1:string;const s2:string);
  48. procedure ReplaceCase(var s:string;const s1,s2:string);
  49. Function MatchPattern(const pattern,what:string):boolean;
  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 realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  59. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  60. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  61. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  62. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  63. function DStr(l:longint):string;
  64. {# Returns true if the string s is a number }
  65. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  66. {# Returns true if value is a power of 2, the actual
  67. exponent value is returned in power.
  68. }
  69. function ispowerof2(value : int64;out power : longint) : boolean;
  70. function nextpowerof2(value : int64; out power: longint) : int64;
  71. function backspace_quote(const s:string;const qchars:Tcharset):string;
  72. function octal_quote(const s:string;const qchars:Tcharset):string;
  73. function maybequoted(const s:string):string;
  74. {# If the string is quoted, in accordance with pascal, it is
  75. dequoted and returned in s, and the function returns true.
  76. If it is not quoted, or if the quoting is bad, s is not touched,
  77. and false is returned.
  78. }
  79. function DePascalQuote(var s: string): Boolean;
  80. function CompareStr(const S1, S2: string): Integer;
  81. function CompareText(S1, S2: string): integer;
  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. {# makes the character @var(c) lowercase, with spanish, french and german
  95. character set
  96. }
  97. function lowercase(c : char) : char;
  98. { makes zero terminated string to a pascal string }
  99. { the data in p is modified and p is returned }
  100. function pchar2pstring(p : pchar) : pstring;
  101. { ambivalent to pchar2pstring }
  102. function pstring2pchar(p : pstring) : pchar;
  103. { Speed/Hash value }
  104. Function GetSpeedValue(Const s:String):cardinal;
  105. { Ansistring (pchar+length) support }
  106. procedure ansistringdispose(var p : pchar;length : longint);
  107. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  108. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  109. {Lzw encode/decode to compress strings -> save memory.}
  110. function minilzw_encode(const s:string):string;
  111. function minilzw_decode(const s:string):string;
  112. implementation
  113. uses
  114. strings
  115. ;
  116. var
  117. uppertbl,
  118. lowertbl : array[char] of char;
  119. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  120. {
  121. return the minimal of a and b
  122. }
  123. begin
  124. if a<=b then
  125. min:=a
  126. else
  127. min:=b;
  128. end;
  129. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  130. {
  131. return the minimal of a and b
  132. }
  133. begin
  134. if a<=b then
  135. min:=a
  136. else
  137. min:=b;
  138. end;
  139. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  140. {
  141. return the maximum of a and b
  142. }
  143. begin
  144. if a>=b then
  145. max:=a
  146. else
  147. max:=b;
  148. end;
  149. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  150. {
  151. return the maximum of a and b
  152. }
  153. begin
  154. if a>=b then
  155. max:=a
  156. else
  157. max:=b;
  158. end;
  159. Function SwapLong(x : longint): longint;{$ifdef USEINLINE}inline;{$endif}
  160. var
  161. y : word;
  162. z : word;
  163. Begin
  164. y := x shr 16;
  165. y := word(longint(y) shl 8) or (y shr 8);
  166. z := x and $FFFF;
  167. z := word(longint(z) shl 8) or (z shr 8);
  168. SwapLong := (longint(z) shl 16) or longint(y);
  169. End;
  170. Function SwapInt64(x : int64): int64;{$ifdef USEINLINE}inline;{$endif}
  171. Begin
  172. result:=swaplong(longint(hi(x)));
  173. result:=result or (swaplong(longint(lo(x))) shl 32);
  174. End;
  175. Function SwapQWord(x : qword) : qword;{$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) : shortint;
  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:shortint):shortint;
  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 MatchPattern(const pattern,what:string):boolean;
  294. var
  295. found : boolean;
  296. i1,i2 : longint;
  297. begin
  298. i1:=0;
  299. i2:=0;
  300. if pattern='' then
  301. begin
  302. result:=(what='');
  303. exit;
  304. end;
  305. found:=true;
  306. repeat
  307. inc(i1);
  308. if (i1>length(pattern)) then
  309. break;
  310. inc(i2);
  311. if (i2>length(what)) then
  312. break;
  313. case pattern[i1] of
  314. '?' :
  315. found:=true;
  316. '*' :
  317. begin
  318. found:=true;
  319. if (i1=length(pattern)) then
  320. i2:=length(what)
  321. else
  322. if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
  323. begin
  324. if i2<length(what) then
  325. dec(i1)
  326. end
  327. else
  328. if i2>1 then
  329. dec(i2);
  330. end;
  331. else
  332. found:=(pattern[i1]=what[i2]) or (what[i2]='?');
  333. end;
  334. until not found;
  335. if found then
  336. begin
  337. found:=(i2>=length(what)) and
  338. (
  339. (i1>length(pattern)) or
  340. ((i1=length(pattern)) and
  341. (pattern[i1]='*'))
  342. );
  343. end;
  344. result:=found;
  345. end;
  346. function upper(const s : string) : string;
  347. {
  348. return uppercased string of s
  349. }
  350. var
  351. i : longint;
  352. begin
  353. for i:=1 to length(s) do
  354. upper[i]:=uppertbl[s[i]];
  355. upper[0]:=s[0];
  356. end;
  357. function lower(const s : string) : string;
  358. {
  359. return lowercased string of s
  360. }
  361. var
  362. i : longint;
  363. begin
  364. for i:=1 to length(s) do
  365. lower[i]:=lowertbl[s[i]];
  366. lower[0]:=s[0];
  367. end;
  368. procedure uppervar(var s : string);
  369. {
  370. uppercase string s
  371. }
  372. var
  373. i : longint;
  374. begin
  375. for i:=1 to length(s) do
  376. s[i]:=uppertbl[s[i]];
  377. end;
  378. procedure initupperlower;
  379. var
  380. c : char;
  381. begin
  382. for c:=#0 to #255 do
  383. begin
  384. lowertbl[c]:=c;
  385. uppertbl[c]:=c;
  386. case c of
  387. 'A'..'Z' :
  388. lowertbl[c]:=char(byte(c)+32);
  389. 'a'..'z' :
  390. uppertbl[c]:=char(byte(c)-32);
  391. end;
  392. end;
  393. end;
  394. function DStr(l:longint):string;
  395. var
  396. TmpStr : string[32];
  397. i : longint;
  398. begin
  399. Str(l,TmpStr);
  400. i:=Length(TmpStr);
  401. while (i>3) do
  402. begin
  403. dec(i,3);
  404. if TmpStr[i]<>'-' then
  405. insert('.',TmpStr,i+1);
  406. end;
  407. DStr:=TmpStr;
  408. end;
  409. function trimbspace(const s:string):string;
  410. {
  411. return s with all leading spaces and tabs removed
  412. }
  413. var
  414. i,j : longint;
  415. begin
  416. j:=1;
  417. i:=length(s);
  418. while (j<i) and (s[j] in [#9,' ']) do
  419. inc(j);
  420. trimbspace:=Copy(s,j,i-j+1);
  421. end;
  422. function trimspace(const s:string):string;
  423. {
  424. return s with all leading and ending spaces and tabs removed
  425. }
  426. var
  427. i,j : longint;
  428. begin
  429. i:=length(s);
  430. while (i>0) and (s[i] in [#9,' ']) do
  431. dec(i);
  432. j:=1;
  433. while (j<i) and (s[j] in [#9,' ']) do
  434. inc(j);
  435. trimspace:=Copy(s,j,i-j+1);
  436. end;
  437. function space (b : longint): string;
  438. var
  439. s: string;
  440. begin
  441. space[0] := chr(b);
  442. s[0] := chr(b);
  443. FillChar (S[1],b,' ');
  444. space:=s;
  445. end;
  446. function PadSpace(const s:string;len:longint):string;
  447. {
  448. return s with spaces add to the end
  449. }
  450. begin
  451. if length(s)<len then
  452. PadSpace:=s+Space(len-length(s))
  453. else
  454. PadSpace:=s;
  455. end;
  456. function GetToken(var s:string;endchar:char):string;
  457. var
  458. i : longint;
  459. begin
  460. GetToken:='';
  461. s:=TrimSpace(s);
  462. if (length(s)>0) and
  463. (s[1]='''') then
  464. begin
  465. i:=1;
  466. while (i<length(s)) do
  467. begin
  468. inc(i);
  469. if s[i]='''' then
  470. begin
  471. { Remove double quote }
  472. if (i<length(s)) and
  473. (s[i+1]='''') then
  474. begin
  475. Delete(s,i,1);
  476. inc(i);
  477. end
  478. else
  479. begin
  480. GetToken:=Copy(s,2,i-2);
  481. Delete(s,1,i);
  482. exit;
  483. end;
  484. end;
  485. end;
  486. GetToken:=s;
  487. s:='';
  488. end
  489. else
  490. begin
  491. i:=pos(EndChar,s);
  492. if i=0 then
  493. begin
  494. GetToken:=s;
  495. s:='';
  496. exit;
  497. end
  498. else
  499. begin
  500. GetToken:=Copy(s,1,i-1);
  501. Delete(s,1,i);
  502. exit;
  503. end;
  504. end;
  505. end;
  506. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  507. begin
  508. str(e,result);
  509. end;
  510. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  511. {
  512. return string of value i
  513. }
  514. begin
  515. str(i,result);
  516. end;
  517. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  518. {
  519. return string of value i
  520. }
  521. begin
  522. str(i,result);
  523. end;
  524. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  525. {
  526. return string of value i
  527. }
  528. begin
  529. str(i,result);
  530. end;
  531. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  532. {
  533. return string of value i, but always include a + when i>=0
  534. }
  535. begin
  536. str(i,result);
  537. if i>=0 then
  538. result:='+'+result;
  539. end;
  540. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  541. {
  542. is string a correct number ?
  543. }
  544. var
  545. w : integer;
  546. l : longint;
  547. begin
  548. val(s,l,w);
  549. // remove warning
  550. l:=l;
  551. is_number:=(w=0);
  552. end;
  553. function ispowerof2(value : int64;out power : longint) : boolean;
  554. {
  555. return if value is a power of 2. And if correct return the power
  556. }
  557. var
  558. hl : int64;
  559. i : longint;
  560. begin
  561. if value and (value - 1) <> 0 then
  562. begin
  563. ispowerof2 := false;
  564. exit
  565. end;
  566. hl:=1;
  567. ispowerof2:=true;
  568. for i:=0 to 63 do
  569. begin
  570. if hl=value then
  571. begin
  572. power:=i;
  573. exit;
  574. end;
  575. hl:=hl shl 1;
  576. end;
  577. ispowerof2:=false;
  578. end;
  579. function nextpowerof2(value : int64; out power: longint) : int64;
  580. {
  581. returns the power of 2 >= value
  582. }
  583. var
  584. i : longint;
  585. begin
  586. result := 0;
  587. power := -1;
  588. if ((value <= 0) or
  589. (value >= $4000000000000000)) then
  590. exit;
  591. result := 1;
  592. for i:=0 to 63 do
  593. begin
  594. if result>=value then
  595. begin
  596. power := i;
  597. exit;
  598. end;
  599. result:=result shl 1;
  600. end;
  601. end;
  602. function backspace_quote(const s:string;const qchars:Tcharset):string;
  603. var i:byte;
  604. begin
  605. backspace_quote:='';
  606. for i:=1 to length(s) do
  607. begin
  608. if (s[i]=#10) and (#10 in qchars) then
  609. backspace_quote:=backspace_quote+'\n'
  610. else if (s[i]=#13) and (#13 in qchars) then
  611. backspace_quote:=backspace_quote+'\r'
  612. else
  613. begin
  614. if s[i] in qchars then
  615. backspace_quote:=backspace_quote+'\';
  616. backspace_quote:=backspace_quote+s[i];
  617. end;
  618. end;
  619. end;
  620. function octal_quote(const s:string;const qchars:Tcharset):string;
  621. var i:byte;
  622. begin
  623. octal_quote:='';
  624. for i:=1 to length(s) do
  625. begin
  626. if s[i] in qchars then
  627. begin
  628. if ord(s[i])<64 then
  629. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  630. else
  631. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  632. end
  633. else
  634. octal_quote:=octal_quote+s[i];
  635. end;
  636. end;
  637. function maybequoted(const s:string):string;
  638. var
  639. s1 : string;
  640. i : integer;
  641. quoted : boolean;
  642. begin
  643. quoted:=false;
  644. s1:='"';
  645. for i:=1 to length(s) do
  646. begin
  647. case s[i] of
  648. '"' :
  649. begin
  650. quoted:=true;
  651. s1:=s1+'\"';
  652. end;
  653. ' ',
  654. #128..#255 :
  655. begin
  656. quoted:=true;
  657. s1:=s1+s[i];
  658. end;
  659. else
  660. s1:=s1+s[i];
  661. end;
  662. end;
  663. if quoted then
  664. maybequoted:=s1+'"'
  665. else
  666. maybequoted:=s;
  667. end;
  668. function DePascalQuote(var s: string): Boolean;
  669. var
  670. destPos, sourcePos, len: Integer;
  671. t: string;
  672. ch: Char;
  673. begin
  674. DePascalQuote:= false;
  675. len:= length(s);
  676. if (len >= 1) and (s[1] = '''') then
  677. begin
  678. {Remove quotes, exchange '' against ' }
  679. destPos := 0;
  680. sourcepos:=1;
  681. while (sourcepos<len) do
  682. begin
  683. inc(sourcePos);
  684. ch := s[sourcePos];
  685. if ch = '''' then
  686. begin
  687. inc(sourcePos);
  688. if (sourcePos <= len) and (s[sourcePos] = '''') then
  689. {Add the quote as part of string}
  690. else
  691. begin
  692. SetLength(t, destPos);
  693. s:= t;
  694. Exit(true);
  695. end;
  696. end;
  697. inc(destPos);
  698. t[destPos] := ch;
  699. end;
  700. end;
  701. end;
  702. function pchar2pstring(p : pchar) : pstring;
  703. var
  704. w,i : longint;
  705. begin
  706. w:=strlen(p);
  707. for i:=w-1 downto 0 do
  708. p[i+1]:=p[i];
  709. p[0]:=chr(w);
  710. pchar2pstring:=pstring(p);
  711. end;
  712. function pstring2pchar(p : pstring) : pchar;
  713. var
  714. w,i : longint;
  715. begin
  716. w:=length(p^);
  717. for i:=1 to w do
  718. p^[i-1]:=p^[i];
  719. p^[w]:=#0;
  720. pstring2pchar:=pchar(p);
  721. end;
  722. function lowercase(c : char) : char;
  723. begin
  724. case c of
  725. #65..#90 : c := chr(ord (c) + 32);
  726. #154 : c:=#129; { german }
  727. #142 : c:=#132; { german }
  728. #153 : c:=#148; { german }
  729. #144 : c:=#130; { french }
  730. #128 : c:=#135; { french }
  731. #143 : c:=#134; { swedish/norge (?) }
  732. #165 : c:=#164; { spanish }
  733. #228 : c:=#229; { greek }
  734. #226 : c:=#231; { greek }
  735. #232 : c:=#227; { greek }
  736. end;
  737. lowercase := c;
  738. end;
  739. function strpnew(const s : string) : pchar;
  740. var
  741. p : pchar;
  742. begin
  743. getmem(p,length(s)+1);
  744. strpcopy(p,s);
  745. strpnew:=p;
  746. end;
  747. procedure strdispose(var p : pchar);
  748. begin
  749. if assigned(p) then
  750. begin
  751. freemem(p,strlen(p)+1);
  752. p:=nil;
  753. end;
  754. end;
  755. procedure stringdispose(var p : pstring);{$ifdef USEINLINE}inline;{$endif}
  756. begin
  757. if assigned(p) then
  758. begin
  759. freemem(p,length(p^)+1);
  760. p:=nil;
  761. end;
  762. end;
  763. function stringdup(const s : string) : pstring;{$ifdef USEINLINE}inline;{$endif}
  764. begin
  765. getmem(result,length(s)+1);
  766. result^:=s;
  767. end;
  768. function CompareStr(const S1, S2: string): Integer;
  769. var
  770. count, count1, count2: integer;
  771. begin
  772. result := 0;
  773. Count1 := Length(S1);
  774. Count2 := Length(S2);
  775. if Count1>Count2 then
  776. Count:=Count2
  777. else
  778. Count:=Count1;
  779. result := CompareChar(S1[1],S2[1], Count);
  780. if result=0 then
  781. result:=Count1-Count2;
  782. end;
  783. function CompareText(S1, S2: string): integer;
  784. begin
  785. UpperVar(S1);
  786. UpperVar(S2);
  787. Result:=CompareStr(S1,S2);
  788. end;
  789. {*****************************************************************************
  790. GetSpeedValue
  791. *****************************************************************************}
  792. var
  793. Crc32Tbl : array[0..255] of cardinal;
  794. procedure MakeCRC32Tbl;
  795. var
  796. crc : cardinal;
  797. i,n : integer;
  798. begin
  799. for i:=0 to 255 do
  800. begin
  801. crc:=i;
  802. for n:=1 to 8 do
  803. if odd(longint(crc)) then
  804. crc:=cardinal(crc shr 1) xor cardinal($edb88320)
  805. else
  806. crc:=cardinal(crc shr 1);
  807. Crc32Tbl[i]:=crc;
  808. end;
  809. end;
  810. Function GetSpeedValue(Const s:String):cardinal;
  811. var
  812. i : integer;
  813. InitCrc : cardinal;
  814. begin
  815. InitCrc:=cardinal($ffffffff);
  816. for i:=1 to Length(s) do
  817. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  818. GetSpeedValue:=InitCrc;
  819. end;
  820. {*****************************************************************************
  821. Ansistring (PChar+Length)
  822. *****************************************************************************}
  823. procedure ansistringdispose(var p : pchar;length : longint);
  824. begin
  825. if assigned(p) then
  826. begin
  827. freemem(p,length+1);
  828. p:=nil;
  829. end;
  830. end;
  831. { enable ansistring comparison }
  832. { 0 means equal }
  833. { 1 means p1 > p2 }
  834. { -1 means p1 < p2 }
  835. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  836. var
  837. i,j : longint;
  838. begin
  839. compareansistrings:=0;
  840. j:=min(length1,length2);
  841. i:=0;
  842. while (i<j) do
  843. begin
  844. if p1[i]>p2[i] then
  845. begin
  846. compareansistrings:=1;
  847. exit;
  848. end
  849. else
  850. if p1[i]<p2[i] then
  851. begin
  852. compareansistrings:=-1;
  853. exit;
  854. end;
  855. inc(i);
  856. end;
  857. if length1>length2 then
  858. compareansistrings:=1
  859. else
  860. if length1<length2 then
  861. compareansistrings:=-1;
  862. end;
  863. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  864. var
  865. p : pchar;
  866. begin
  867. getmem(p,length1+length2+1);
  868. move(p1[0],p[0],length1);
  869. move(p2[0],p[length1],length2+1);
  870. concatansistrings:=p;
  871. end;
  872. {*****************************************************************************
  873. Ultra basic KISS Lzw (de)compressor
  874. *****************************************************************************}
  875. {This is an extremely basic implementation of the Lzw algorithm. It
  876. compresses 7-bit ASCII strings into 8-bit compressed strings.
  877. The Lzw dictionary is preinitialized with 0..127, therefore this
  878. part of the dictionary does not need to be stored in the arrays.
  879. The Lzw code size is allways 8 bit, so we do not need complex code
  880. that can write partial bytes.}
  881. function minilzw_encode(const s:string):string;
  882. var t,u,i:byte;
  883. c:char;
  884. data:array[128..255] of char;
  885. previous:array[128..255] of byte;
  886. lzwptr:byte;
  887. next_avail:set of 0..255;
  888. label l1;
  889. begin
  890. minilzw_encode:='';
  891. if s<>'' then
  892. begin
  893. lzwptr:=127;
  894. t:=byte(s[1]);
  895. i:=2;
  896. u:=128;
  897. next_avail:=[];
  898. while i<=length(s) do
  899. begin
  900. c:=s[i];
  901. if not(t in next_avail) or (u>lzwptr) then goto l1;
  902. while (previous[u]<>t) or (data[u]<>c) do
  903. begin
  904. inc(u);
  905. if u>lzwptr then goto l1;
  906. end;
  907. t:=u;
  908. inc(i);
  909. continue;
  910. l1:
  911. {It's a pity that we still need those awfull tricks
  912. with this modern compiler. Without this performance
  913. of the entire procedure drops about 3 times.}
  914. inc(minilzw_encode[0]);
  915. minilzw_encode[length(minilzw_encode)]:=char(t);
  916. if lzwptr=255 then
  917. begin
  918. lzwptr:=127;
  919. next_avail:=[];
  920. end
  921. else
  922. begin
  923. inc(lzwptr);
  924. data[lzwptr]:=c;
  925. previous[lzwptr]:=t;
  926. include(next_avail,t);
  927. end;
  928. t:=byte(c);
  929. u:=128;
  930. inc(i);
  931. end;
  932. inc(minilzw_encode[0]);
  933. minilzw_encode[length(minilzw_encode)]:=char(t);
  934. end;
  935. end;
  936. function minilzw_decode(const s:string):string;
  937. var oldc,newc,c:char;
  938. i,j:byte;
  939. data:array[128..255] of char;
  940. previous:array[128..255] of byte;
  941. lzwptr:byte;
  942. t:string;
  943. begin
  944. minilzw_decode:='';
  945. if s<>'' then
  946. begin
  947. lzwptr:=127;
  948. oldc:=s[1];
  949. c:=oldc;
  950. i:=2;
  951. minilzw_decode:=oldc;
  952. while i<=length(s) do
  953. begin
  954. newc:=s[i];
  955. if byte(newc)>lzwptr then
  956. begin
  957. t:=c;
  958. c:=oldc;
  959. end
  960. else
  961. begin
  962. c:=newc;
  963. t:='';
  964. end;
  965. while c>=#128 do
  966. begin
  967. inc(t[0]);
  968. t[length(t)]:=data[byte(c)];
  969. byte(c):=previous[byte(c)];
  970. end;
  971. inc(minilzw_decode[0]);
  972. minilzw_decode[length(minilzw_decode)]:=c;
  973. for j:=length(t) downto 1 do
  974. begin
  975. inc(minilzw_decode[0]);
  976. minilzw_decode[length(minilzw_decode)]:=t[j];
  977. end;
  978. if lzwptr=255 then
  979. lzwptr:=127
  980. else
  981. begin
  982. inc(lzwptr);
  983. previous[lzwptr]:=byte(oldc);
  984. data[lzwptr]:=c;
  985. end;
  986. oldc:=newc;
  987. inc(i);
  988. end;
  989. end;
  990. end;
  991. procedure defaulterror(i:longint);
  992. begin
  993. writeln('Internal error ',i);
  994. runerror(255);
  995. end;
  996. initialization
  997. internalerrorproc:=@defaulterror;
  998. makecrc32tbl;
  999. initupperlower;
  1000. end.