cutils.pas 31 KB

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