cutils.pas 31 KB

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