cutils.pas 30 KB

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