cutils.pas 36 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367
  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. uses
  24. constexp;
  25. type
  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. function min(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  33. {# Returns the maximum value between @var(a) and @var(b) }
  34. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  35. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  36. function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  37. { These functions are intenionally put here and not in the constexp unit.
  38. Since Tconstexprint may be automatically converted to int, which causes
  39. loss of data and since there are already min and max functions for ints in
  40. this unit, we put min and max for Tconstexprint as well. This way we avoid
  41. potential bugs, caused by code unintentionally calling the int versions of
  42. min/max on Tconstexprint, because of only including cutils and forgetting
  43. the constexp unit in the uses clause. }
  44. function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  45. function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  46. {# Return value @var(i) aligned on @var(a) boundary }
  47. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  48. function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
  49. function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
  50. { if you have an address aligned using "oldalignment" and add an
  51. offset of (a multiple of) offset to it, this function calculates
  52. the new minimally guaranteed alignment
  53. }
  54. function newalignment(oldalignment: longint; offset: int64): longint;
  55. {# Return @var(b) with the bit order reversed }
  56. function reverse_byte(b: byte): byte;
  57. {# Return @var(w) with the bit order reversed }
  58. function reverse_word(w: word): word;
  59. {# Return @var(l) with the bit order reversed }
  60. function reverse_longword(l: longword): longword;
  61. function next_prime(l: longint): longint;
  62. function used_align(varalign,minalign,maxalign:longint):longint;
  63. function isbetteralignedthan(new, org, limit: cardinal): boolean;
  64. function packedbitsloadsize(bitlen: int64) : int64;
  65. procedure Replace(var s:string;s1:string;const s2:string);
  66. procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
  67. procedure ReplaceCase(var s:string;const s1,s2:string);
  68. procedure ReplaceCase(var s:ansistring;const s1,s2:ansistring);
  69. Function MatchPattern(const pattern,what:string):boolean;
  70. function upper(const c : char) : char;
  71. function upper(const s : string) : string;
  72. function upper(const s : ansistring) : ansistring;
  73. function lower(const c : char) : char;
  74. function lower(const s : string) : string;
  75. function lower(const s : ansistring) : ansistring;
  76. function rpos(const needle: char; const haystack: shortstring): longint; overload;
  77. function rpos(const needle: shortstring; const haystack: shortstring): longint; overload;
  78. function trimspace(const s:string):string;
  79. function trimspace(const s:AnsiString):AnsiString;
  80. function space (b : longint): string;
  81. { returns the position of the first char of the set cs in s, if there is none, then it returns 0 }
  82. function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
  83. function PadSpace(const s:string;len:longint):string;
  84. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  85. function GetToken(var s:string;endchar:char):string;
  86. function GetToken(var s:ansistring;endchar:char):ansistring;
  87. procedure uppervar(var s : string);
  88. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  89. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  90. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  91. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  92. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  93. function DStr(l:longint):string;
  94. {# Returns true if the string s is a number }
  95. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  96. {# Returns true if value is a power of 2, the actual
  97. exponent value is returned in power.
  98. }
  99. function ispowerof2(value : int64;out power : longint) : boolean;
  100. function ispowerof2(const value : Tconstexprint;out power : longint) : boolean;
  101. {# Returns true if abs(value) is a power of 2, the actual
  102. exponent value is returned in power.
  103. }
  104. function isabspowerof2(const value : Tconstexprint; out power : longint) : boolean;
  105. { # Returns the power of 2 >= value }
  106. function nextpowerof2(value : qword; out power: longint) : qword;
  107. function backspace_quote(const s:string;const qchars:Tcharset):string;
  108. function octal_quote(const s:string;const qchars:Tcharset):string;
  109. {# If the string is quoted, in accordance with pascal, it is
  110. dequoted and returned in s, and the function returns true.
  111. If it is not quoted, or if the quoting is bad, s is not touched,
  112. and false is returned.
  113. }
  114. function DePascalQuote(var s: ansistring): Boolean;
  115. function CompareStr(const S1, S2: string): Integer;
  116. function CompareText(S1, S2: string): integer;
  117. { releases the string p and assignes nil to p }
  118. { if p=nil then freemem isn't called }
  119. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  120. { allocates mem for a copy of s, copies s to this mem and returns }
  121. { a pointer to this mem }
  122. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  123. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  124. {# Allocates memory for the string @var(s) and copies s as zero
  125. terminated string to that allocated memory and returns a pointer
  126. to that mem
  127. }
  128. function strpnew(const s : string) : pchar;
  129. function strpnew(const s : ansistring) : pchar;
  130. {# makes the character @var(c) lowercase, with spanish, french and german
  131. character set
  132. }
  133. function lowercase(c : char) : char;
  134. { allocate a new pchar with the contents of a}
  135. function ansistring2pchar(const a: ansistring) : pchar;
  136. { Ansistring (pchar+length) support }
  137. procedure ansistringdispose(var p : pchar;length : longint);
  138. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  139. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  140. function LengthUleb128(a: qword) : byte;
  141. function LengthSleb128(a: int64) : byte;
  142. function EncodeUleb128(a: qword;out buf;len: byte) : byte;
  143. function EncodeSleb128(a: int64;out buf;len: byte) : byte;
  144. { hide Sysutils.ExecuteProcess in units using this one after SysUtils}
  145. const
  146. ExecuteProcess = 'Do not use' deprecated 'Use cfileutil.RequotedExecuteProcess instead, ExecuteProcess cannot deal with single quotes as used by Unix command lines';
  147. implementation
  148. uses
  149. SysUtils;
  150. var
  151. uppertbl,
  152. lowertbl : array[char] of char;
  153. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  154. {
  155. return the minimal of a and b
  156. }
  157. begin
  158. if a<=b then
  159. min:=a
  160. else
  161. min:=b;
  162. end;
  163. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  164. {
  165. return the minimal of a and b
  166. }
  167. begin
  168. if a<=b then
  169. min:=a
  170. else
  171. min:=b;
  172. end;
  173. function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  174. {
  175. return the minimal of a and b
  176. }
  177. begin
  178. if a<=b then
  179. min:=a
  180. else
  181. min:=b;
  182. end;
  183. function min(a,b : qword) : qword;
  184. {
  185. return the minimal of a and b
  186. }
  187. begin
  188. if a<=b then
  189. min:=a
  190. else
  191. min:=b;
  192. end;
  193. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  194. {
  195. return the maximum of a and b
  196. }
  197. begin
  198. if a>=b then
  199. max:=a
  200. else
  201. max:=b;
  202. end;
  203. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  204. {
  205. return the maximum of a and b
  206. }
  207. begin
  208. if a>=b then
  209. max:=a
  210. else
  211. max:=b;
  212. end;
  213. function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  214. {
  215. return the maximum of a and b
  216. }
  217. begin
  218. if a>=b then
  219. max:=a
  220. else
  221. max:=b;
  222. end;
  223. function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  224. {
  225. return the maximum of a and b
  226. }
  227. begin
  228. if a>=b then
  229. max:=a
  230. else
  231. max:=b;
  232. end;
  233. function newalignment(oldalignment: longint; offset: int64): longint;
  234. begin
  235. { oldalignment must be power of two.
  236. Negating two's complement number keeps its tail '100...000' and complements all bits above.
  237. "x and -x" extracts this tail of 'x'.
  238. Said tail of "oldalignment or offset" is the desired answer. }
  239. result:=oldalignment or longint(offset); { high part of offset won't matter as long as alignment is 32-bit }
  240. result:=result and -result;
  241. end;
  242. function reverse_byte(b: byte): byte;
  243. const
  244. reverse_nible:array[0..15] of 0..15 =
  245. (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
  246. %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
  247. begin
  248. reverse_byte:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
  249. end;
  250. function reverse_word(w: word): word;
  251. type
  252. TWordRec = packed record
  253. hi, lo: Byte;
  254. end;
  255. begin
  256. TWordRec(reverse_word).hi := reverse_byte(TWordRec(w).lo);
  257. TWordRec(reverse_word).lo := reverse_byte(TWordRec(w).hi);
  258. end;
  259. function reverse_longword(l: longword): longword;
  260. type
  261. TLongWordRec = packed record
  262. b: array[0..3] of Byte;
  263. end;
  264. begin
  265. TLongWordRec(reverse_longword).b[0] := reverse_byte(TLongWordRec(l).b[3]);
  266. TLongWordRec(reverse_longword).b[1] := reverse_byte(TLongWordRec(l).b[2]);
  267. TLongWordRec(reverse_longword).b[2] := reverse_byte(TLongWordRec(l).b[1]);
  268. TLongWordRec(reverse_longword).b[3] := reverse_byte(TLongWordRec(l).b[0]);
  269. end;
  270. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  271. {
  272. return value <i> aligned <a> boundary. <a> must be power of two.
  273. }
  274. begin
  275. { One-line formula for i >= 0 is
  276. >>> (i + a - 1) and not (a - 1),
  277. and for i < 0 is
  278. >>> i and not (a - 1). }
  279. if a>0 then
  280. a:=a-1; { 'a' is decremented beforehand, this also allows a=0 as a synonym for a=1. }
  281. if i>=0 then
  282. i:=i+a;
  283. result:=i and not a;
  284. end;
  285. function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
  286. {
  287. return value <i> aligned <a> boundary. <a> must be power of two.
  288. }
  289. begin
  290. { Copy of 'longint' version. }
  291. if a>0 then
  292. a:=a-1;
  293. if i>=0 then
  294. i:=i+a;
  295. result:=i and not a;
  296. end;
  297. function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
  298. {
  299. return value <i> aligned <a> boundary. <a> must be power of two.
  300. }
  301. begin
  302. { No i < 0 case here. }
  303. if a>0 then
  304. a:=a-1;
  305. result:=(i+a) and not a;
  306. end;
  307. function packedbitsloadsize(bitlen: int64) : int64;
  308. begin
  309. case bitlen of
  310. 1,2,4,8:
  311. result := 1;
  312. { 10 bits can never be split over 3 bytes via 1-8-1, because it }
  313. { always starts at a multiple of 10 bits. Same for the others. }
  314. 3,5,6,7,9,10,12,16:
  315. result := 2;
  316. {$ifdef cpu64bitalu}
  317. { performance penalty for unaligned 8 byte access is much }
  318. { higher than for unaligned 4 byte access, at least on ppc, }
  319. { so use 4 bytes even in some cases where a value could }
  320. { always loaded using a single 8 byte load (e.g. in case of }
  321. { 28 bit values) }
  322. 11,13,14,15,17..32:
  323. result := 4;
  324. else
  325. result := 8;
  326. {$else cpu64bitalu}
  327. else
  328. result := 4;
  329. {$endif cpu64bitalu}
  330. end;
  331. end;
  332. function isbetteralignedthan(new, org, limit: cardinal): boolean;
  333. var
  334. cnt: cardinal;
  335. begin
  336. cnt:=2;
  337. while (cnt <= limit) do
  338. begin
  339. if (org and (cnt-1)) > (new and (cnt-1)) then
  340. begin
  341. result:=true;
  342. exit;
  343. end
  344. else if (org and (cnt-1)) < (new and (cnt-1)) then
  345. begin
  346. result:=false;
  347. exit;
  348. end;
  349. cnt:=cnt*2;
  350. end;
  351. result:=false;
  352. end;
  353. function next_prime(l: longint): longint;
  354. var
  355. check, checkbound: longint;
  356. ok: boolean;
  357. begin
  358. result:=l or 1;
  359. while l<high(longint) do
  360. begin
  361. ok:=true;
  362. checkbound:=trunc(sqrt(l));
  363. check:=3;
  364. while check<checkbound do
  365. begin
  366. if (l mod check) = 0 then
  367. begin
  368. ok:=false;
  369. break;
  370. end;
  371. inc(check,2);
  372. end;
  373. if ok then
  374. exit;
  375. inc(l);
  376. end;
  377. end;
  378. function used_align(varalign,minalign,maxalign:longint):longint;
  379. begin
  380. { varalign : minimum alignment required for the variable
  381. minalign : Minimum alignment of this structure, 0 = undefined
  382. maxalign : Maximum alignment of this structure, 0 = undefined }
  383. if (minalign>0) and
  384. (varalign<=minalign) then
  385. used_align:=minalign
  386. else
  387. begin
  388. if (maxalign>0) and
  389. (varalign>maxalign) then
  390. used_align:=maxalign
  391. else
  392. used_align:=varalign;
  393. end;
  394. end;
  395. procedure Replace(var s:string;s1:string;const s2:string);
  396. var
  397. last,
  398. i : longint;
  399. begin
  400. s1:=upper(s1);
  401. last:=0;
  402. repeat
  403. i:=pos(s1,upper(s));
  404. if i=last then
  405. i:=0;
  406. if (i>0) then
  407. begin
  408. Delete(s,i,length(s1));
  409. Insert(s2,s,i);
  410. last:=i;
  411. end;
  412. until (i=0);
  413. end;
  414. procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
  415. var
  416. last,
  417. i : longint;
  418. begin
  419. s1:=upper(s1);
  420. last:=0;
  421. repeat
  422. i:=pos(s1,upper(s));
  423. if i=last then
  424. i:=0;
  425. if (i>0) then
  426. begin
  427. Delete(s,i,length(s1));
  428. Insert(s2,s,i);
  429. last:=i;
  430. end;
  431. until (i=0);
  432. end;
  433. procedure ReplaceCase(var s:string;const s1,s2:string);
  434. var
  435. last,
  436. i : longint;
  437. begin
  438. last:=0;
  439. repeat
  440. i:=pos(s1,s);
  441. if i=last then
  442. i:=0;
  443. if (i>0) then
  444. begin
  445. Delete(s,i,length(s1));
  446. Insert(s2,s,i);
  447. last:=i;
  448. end;
  449. until (i=0);
  450. end;
  451. procedure ReplaceCase(var s: ansistring; const s1, s2: ansistring);
  452. var
  453. last,
  454. i : longint;
  455. begin
  456. last:=0;
  457. repeat
  458. i:=pos(s1,s);
  459. if i=last then
  460. i:=0;
  461. if (i>0) then
  462. begin
  463. Delete(s,i,length(s1));
  464. Insert(s2,s,i);
  465. last:=i;
  466. end;
  467. until (i=0);
  468. end;
  469. Function MatchPattern(const pattern,what:string):boolean;
  470. var
  471. found : boolean;
  472. i1,i2 : longint;
  473. begin
  474. i1:=0;
  475. i2:=0;
  476. if pattern='' then
  477. begin
  478. result:=(what='');
  479. exit;
  480. end;
  481. found:=true;
  482. repeat
  483. inc(i1);
  484. if (i1>length(pattern)) then
  485. break;
  486. inc(i2);
  487. if (i2>length(what)) then
  488. break;
  489. case pattern[i1] of
  490. '?' :
  491. found:=true;
  492. '*' :
  493. begin
  494. found:=true;
  495. if (i1=length(pattern)) then
  496. i2:=length(what)
  497. else
  498. if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
  499. begin
  500. if i2<length(what) then
  501. dec(i1)
  502. end
  503. else
  504. if i2>1 then
  505. dec(i2);
  506. end;
  507. else
  508. found:=(pattern[i1]=what[i2]) or (what[i2]='?');
  509. end;
  510. until not found;
  511. if found then
  512. begin
  513. found:=(i2>=length(what)) and
  514. (
  515. (i1>length(pattern)) or
  516. ((i1=length(pattern)) and
  517. (pattern[i1]='*'))
  518. );
  519. end;
  520. result:=found;
  521. end;
  522. function upper(const c : char) : char;
  523. {
  524. return uppercase of c
  525. }
  526. begin
  527. upper:=uppertbl[c];
  528. end;
  529. function upper(const s : string) : string;
  530. {
  531. return uppercased string of s
  532. }
  533. var
  534. i : longint;
  535. begin
  536. for i:=1 to length(s) do
  537. upper[i]:=uppertbl[s[i]];
  538. upper[0]:=s[0];
  539. end;
  540. function upper(const s : ansistring) : ansistring;
  541. {
  542. return uppercased string of s
  543. }
  544. var
  545. i,n : sizeint;
  546. begin
  547. Result:=s;
  548. n:=length(s);
  549. i:=0;
  550. while i<n do
  551. if PChar(Pointer(s))[i] in ['a'..'z'] then
  552. begin
  553. UniqueString(Result);
  554. repeat
  555. PChar(Pointer(Result))[i]:=uppertbl[PChar(Pointer(s))[i]];
  556. inc(i);
  557. until i=n;
  558. exit;
  559. end
  560. else
  561. inc(i);
  562. end;
  563. function lower(const c : char) : char;
  564. {
  565. return lowercase of c
  566. }
  567. begin
  568. lower:=lowertbl[c];
  569. end;
  570. function lower(const s : string) : string;
  571. {
  572. return lowercased string of s
  573. }
  574. var
  575. i : longint;
  576. begin
  577. for i:=1 to length(s) do
  578. lower[i]:=lowertbl[s[i]];
  579. lower[0]:=s[0];
  580. end;
  581. function lower(const s : ansistring) : ansistring;
  582. {
  583. return lowercased string of s
  584. }
  585. var
  586. i,n : sizeint;
  587. begin
  588. Result:=s;
  589. n:=length(s);
  590. i:=0;
  591. while i<n do
  592. if PChar(Pointer(s))[i] in ['A'..'Z'] then
  593. begin
  594. UniqueString(Result);
  595. repeat
  596. PChar(Pointer(Result))[i]:=lowertbl[PChar(Pointer(s))[i]];
  597. inc(i);
  598. until i=n;
  599. exit;
  600. end
  601. else
  602. inc(i);
  603. end;
  604. procedure uppervar(var s : string);
  605. {
  606. uppercase string s
  607. }
  608. var
  609. i : longint;
  610. begin
  611. for i:=1 to length(s) do
  612. s[i]:=uppertbl[s[i]];
  613. end;
  614. procedure initupperlower;
  615. var
  616. c : char;
  617. begin
  618. for c:=#0 to #255 do
  619. begin
  620. lowertbl[c]:=c;
  621. uppertbl[c]:=c;
  622. case c of
  623. 'A'..'Z' :
  624. lowertbl[c]:=char(byte(c)+32);
  625. 'a'..'z' :
  626. uppertbl[c]:=char(byte(c)-32);
  627. end;
  628. end;
  629. end;
  630. function DStr(l:longint):string;
  631. var
  632. TmpStr : string[32];
  633. i : longint;
  634. begin
  635. Str(l,TmpStr);
  636. i:=Length(TmpStr);
  637. while (i>3) do
  638. begin
  639. dec(i,3);
  640. if TmpStr[i]<>'-' then
  641. insert('.',TmpStr,i+1);
  642. end;
  643. DStr:=TmpStr;
  644. end;
  645. function rpos(const needle: char; const haystack: shortstring): longint;
  646. begin
  647. result:=length(haystack);
  648. while (result>0) do
  649. begin
  650. if haystack[result]=needle then
  651. exit;
  652. dec(result);
  653. end;
  654. end;
  655. function rpos(const needle: shortstring; const haystack: shortstring): longint;
  656. begin
  657. result:=0;
  658. if (length(needle)=0) or
  659. (length(needle)>length(haystack)) then
  660. exit;
  661. result:=length(haystack)-length(needle)+1;
  662. repeat
  663. if (haystack[result]=needle[1]) and
  664. (CompareByte(haystack[result],needle[1],length(needle))=0) then
  665. exit;
  666. dec(result);
  667. until result=0;
  668. end;
  669. function trimspace(const s:string):string;
  670. {
  671. return s with all leading and ending spaces and tabs removed
  672. }
  673. var
  674. i,j : longint;
  675. begin
  676. i:=length(s);
  677. while (i>0) and (s[i] in [#9,' ']) do
  678. dec(i);
  679. j:=1;
  680. while (j<i) and (s[j] in [#9,' ']) do
  681. inc(j);
  682. trimspace:=Copy(s,j,i-j+1);
  683. end;
  684. function trimspace(const s:AnsiString):AnsiString;
  685. {
  686. return s with all leading and ending spaces and tabs removed
  687. }
  688. var
  689. i,j : longint;
  690. begin
  691. i:=length(s);
  692. while (i>0) and (s[i] in [#9,' ']) do
  693. dec(i);
  694. j:=1;
  695. while (j<i) and (s[j] in [#9,' ']) do
  696. inc(j);
  697. trimspace:=Copy(s,j,i-j+1);
  698. end;
  699. function space (b : longint): string;
  700. var
  701. s: string;
  702. begin
  703. space[0] := chr(b);
  704. s[0] := chr(b);
  705. FillChar (S[1],b,' ');
  706. space:=s;
  707. end;
  708. function PadSpace(const s:string;len:longint):string;
  709. {
  710. return s with spaces add to the end
  711. }
  712. begin
  713. if length(s)<len then
  714. PadSpace:=s+Space(len-length(s))
  715. else
  716. PadSpace:=s;
  717. end;
  718. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  719. {
  720. return s with spaces add to the end
  721. }
  722. begin
  723. if length(s)<len then
  724. PadSpace:=s+Space(len-length(s))
  725. else
  726. PadSpace:=s;
  727. end;
  728. function GetToken(var s:string;endchar:char):string;
  729. var
  730. i : longint;
  731. quote : char;
  732. begin
  733. GetToken:='';
  734. s:=TrimSpace(s);
  735. if (length(s)>0) and
  736. (s[1] in ['''','"']) then
  737. begin
  738. quote:=s[1];
  739. i:=1;
  740. while (i<length(s)) do
  741. begin
  742. inc(i);
  743. if s[i]=quote then
  744. begin
  745. { Remove double quote }
  746. if (i<length(s)) and
  747. (s[i+1]=quote) then
  748. begin
  749. Delete(s,i,1);
  750. inc(i);
  751. end
  752. else
  753. begin
  754. GetToken:=Copy(s,2,i-2);
  755. Delete(s,1,i);
  756. exit;
  757. end;
  758. end;
  759. end;
  760. GetToken:=s;
  761. s:='';
  762. end
  763. else
  764. begin
  765. i:=pos(EndChar,s);
  766. if i=0 then
  767. begin
  768. GetToken:=s;
  769. s:='';
  770. exit;
  771. end
  772. else
  773. begin
  774. GetToken:=Copy(s,1,i-1);
  775. Delete(s,1,i);
  776. exit;
  777. end;
  778. end;
  779. end;
  780. function GetToken(var s:ansistring;endchar:char):ansistring;
  781. var
  782. i : longint;
  783. quote : char;
  784. begin
  785. GetToken:='';
  786. s:=TrimSpace(s);
  787. if (length(s)>0) and
  788. (s[1] in ['''','"']) then
  789. begin
  790. quote:=s[1];
  791. i:=1;
  792. while (i<length(s)) do
  793. begin
  794. inc(i);
  795. if s[i]=quote then
  796. begin
  797. { Remove double quote }
  798. if (i<length(s)) and
  799. (s[i+1]=quote) then
  800. begin
  801. Delete(s,i,1);
  802. inc(i);
  803. end
  804. else
  805. begin
  806. GetToken:=Copy(s,2,i-2);
  807. Delete(s,1,i);
  808. exit;
  809. end;
  810. end;
  811. end;
  812. GetToken:=s;
  813. s:='';
  814. end
  815. else
  816. begin
  817. i:=pos(EndChar,s);
  818. if i=0 then
  819. begin
  820. GetToken:=s;
  821. s:='';
  822. exit;
  823. end
  824. else
  825. begin
  826. GetToken:=Copy(s,1,i-1);
  827. Delete(s,1,i);
  828. exit;
  829. end;
  830. end;
  831. end;
  832. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  833. begin
  834. str(e,result);
  835. end;
  836. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  837. {
  838. return string of value i
  839. }
  840. begin
  841. str(i,result);
  842. end;
  843. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  844. {
  845. return string of value i
  846. }
  847. begin
  848. str(i,result);
  849. end;
  850. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  851. {
  852. return string of value i
  853. }
  854. begin
  855. str(i,result);
  856. end;
  857. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  858. {
  859. return string of value i, but always include a + when i>=0
  860. }
  861. begin
  862. str(i,result);
  863. if i>=0 then
  864. result:='+'+result;
  865. end;
  866. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  867. {
  868. is string a correct number ?
  869. }
  870. var
  871. w : integer;
  872. l : longint;
  873. begin
  874. val(s,l,w);
  875. // remove warning
  876. l:=l;
  877. is_number:=(w=0);
  878. end;
  879. function ispowerof2(value : int64;out power : longint) : boolean;
  880. {
  881. return if value is a power of 2. And if correct return the power
  882. }
  883. begin
  884. if (value <= 0) or (value and (value - 1) <> 0) then
  885. exit(false);
  886. power:=BsfQWord(value);
  887. result:=true;
  888. end;
  889. function ispowerof2(const value: Tconstexprint; out power: longint): boolean;
  890. begin
  891. if value.signed or
  892. (value.uvalue<=high(int64)) then
  893. result:=ispowerof2(value.svalue,power)
  894. else if not value.signed and
  895. (value.svalue=low(int64)) then
  896. begin
  897. result:=true;
  898. power:=63;
  899. end
  900. else
  901. result:=false;
  902. end;
  903. function isabspowerof2(const value : Tconstexprint;out power : longint) : boolean;
  904. begin
  905. if ispowerof2(value,power) then
  906. result:=true
  907. else if value.signed and (value.svalue<0) and (value.svalue<>low(int64)) and ispowerof2(-value.svalue,power) then
  908. result:=true
  909. else
  910. result:=false;
  911. end;
  912. function nextpowerof2(value : qword; out power: longint) : qword;
  913. begin
  914. power:=-1;
  915. result:=0;
  916. if (value=0) or (value>qword($8000000000000000)) then
  917. exit;
  918. power:=BsrQWord(value);
  919. result:=qword(1) shl power;
  920. if (value and (value-1))<>0 then
  921. begin
  922. inc(power);
  923. result:=result shl 1;
  924. end;
  925. end;
  926. function backspace_quote(const s:string;const qchars:Tcharset):string;
  927. var i:byte;
  928. begin
  929. backspace_quote:='';
  930. for i:=1 to length(s) do
  931. begin
  932. if (s[i]=#10) and (#10 in qchars) then
  933. backspace_quote:=backspace_quote+'\n'
  934. else if (s[i]=#13) and (#13 in qchars) then
  935. backspace_quote:=backspace_quote+'\r'
  936. else
  937. begin
  938. if s[i] in qchars then
  939. backspace_quote:=backspace_quote+'\';
  940. backspace_quote:=backspace_quote+s[i];
  941. end;
  942. end;
  943. end;
  944. function octal_quote(const s:string;const qchars:Tcharset):string;
  945. var i:byte;
  946. begin
  947. octal_quote:='';
  948. for i:=1 to length(s) do
  949. begin
  950. if s[i] in qchars then
  951. begin
  952. if ord(s[i])<64 then
  953. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  954. else
  955. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  956. end
  957. else
  958. octal_quote:=octal_quote+s[i];
  959. end;
  960. end;
  961. function DePascalQuote(var s: ansistring): Boolean;
  962. var
  963. destPos, sourcePos, len: Integer;
  964. t: string;
  965. ch: Char;
  966. begin
  967. t:='';
  968. DePascalQuote:= false;
  969. len:= length(s);
  970. if (len >= 1) and (s[1] = '''') then
  971. begin
  972. {Remove quotes, exchange '' against ' }
  973. destPos := 0;
  974. sourcepos:=1;
  975. while (sourcepos<len) do
  976. begin
  977. inc(sourcePos);
  978. ch := s[sourcePos];
  979. if ch = '''' then
  980. begin
  981. inc(sourcePos);
  982. if (sourcePos <= len) and (s[sourcePos] = '''') then
  983. {Add the quote as part of string}
  984. else
  985. begin
  986. SetLength(t, destPos);
  987. s:= t;
  988. Exit(true);
  989. end;
  990. end;
  991. inc(destPos);
  992. t[destPos] := ch;
  993. end;
  994. end;
  995. end;
  996. function ansistring2pchar(const a: ansistring) : pchar;
  997. var
  998. len: ptrint;
  999. begin
  1000. len:=length(a);
  1001. getmem(result,len+1);
  1002. if (len<>0) then
  1003. move(a[1],result[0],len);
  1004. result[len]:=#0;
  1005. end;
  1006. function lowercase(c : char) : char;
  1007. begin
  1008. case c of
  1009. #65..#90 : c := chr(ord (c) + 32);
  1010. #154 : c:=#129; { german }
  1011. #142 : c:=#132; { german }
  1012. #153 : c:=#148; { german }
  1013. #144 : c:=#130; { french }
  1014. #128 : c:=#135; { french }
  1015. #143 : c:=#134; { swedish/norge (?) }
  1016. #165 : c:=#164; { spanish }
  1017. #228 : c:=#229; { greek }
  1018. #226 : c:=#231; { greek }
  1019. #232 : c:=#227; { greek }
  1020. end;
  1021. lowercase := c;
  1022. end;
  1023. function strpnew(const s : string) : pchar;
  1024. var
  1025. p : pchar;
  1026. begin
  1027. getmem(p,length(s)+1);
  1028. move(s[1],p^,length(s));
  1029. p[length(s)]:=#0;
  1030. result:=p;
  1031. end;
  1032. function strpnew(const s: ansistring): pchar;
  1033. var
  1034. p : pchar;
  1035. begin
  1036. getmem(p,length(s)+1);
  1037. move(s[1],p^,length(s)+1);
  1038. result:=p;
  1039. end;
  1040. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  1041. begin
  1042. if assigned(p) then
  1043. begin
  1044. freemem(p);
  1045. p:=nil;
  1046. end;
  1047. end;
  1048. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1049. begin
  1050. getmem(result,length(s)+1);
  1051. result^:=s;
  1052. end;
  1053. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1054. begin
  1055. getmem(result,length(s)+1);
  1056. result^:=s;
  1057. end;
  1058. function PosCharset(const cs : TCharSet;const s : ansistring) : integer;
  1059. var
  1060. i : integer;
  1061. begin
  1062. result:=0;
  1063. for i:=1 to length(s) do
  1064. if s[i] in cs then
  1065. begin
  1066. result:=i;
  1067. exit;
  1068. end;
  1069. end;
  1070. function CompareStr(const S1, S2: string): Integer;
  1071. var
  1072. count, count1, count2: integer;
  1073. begin
  1074. Count1 := Length(S1);
  1075. Count2 := Length(S2);
  1076. if Count1>Count2 then
  1077. Count:=Count2
  1078. else
  1079. Count:=Count1;
  1080. result := CompareByte(S1[1],S2[1], Count);
  1081. if result=0 then
  1082. result:=Count1-Count2;
  1083. end;
  1084. function CompareText(S1, S2: string): integer;
  1085. begin
  1086. UpperVar(S1);
  1087. UpperVar(S2);
  1088. Result:=CompareStr(S1,S2);
  1089. end;
  1090. {*****************************************************************************
  1091. Ansistring (PChar+Length)
  1092. *****************************************************************************}
  1093. procedure ansistringdispose(var p : pchar;length : longint);
  1094. begin
  1095. if assigned(p) then
  1096. begin
  1097. freemem(p);
  1098. p:=nil;
  1099. end;
  1100. end;
  1101. { enable ansistring comparison }
  1102. { 0 means equal }
  1103. { 1 means p1 > p2 }
  1104. { -1 means p1 < p2 }
  1105. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  1106. var
  1107. cmp : SizeInt;
  1108. begin
  1109. cmp:=CompareByte(p1^,p2^,min(length1,length2));
  1110. if cmp=0 then
  1111. cmp:=length1-length2;
  1112. result:=ord(cmp>0)-ord(cmp<0);
  1113. end;
  1114. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  1115. var
  1116. p : pchar;
  1117. begin
  1118. getmem(p,length1+length2+1);
  1119. move(p1[0],p[0],length1);
  1120. move(p2[0],p[length1],length2+1);
  1121. concatansistrings:=p;
  1122. end;
  1123. procedure defaulterror(i:longint);
  1124. begin
  1125. writeln('Internal error ',i);
  1126. runerror(255);
  1127. end;
  1128. function LengthUleb128(a: qword) : byte;
  1129. begin
  1130. result:=0;
  1131. repeat
  1132. inc(result);
  1133. a := a shr 7;
  1134. until a=0;
  1135. end;
  1136. function LengthSleb128(a: int64) : byte;
  1137. begin
  1138. { 'a xor SarInt64(a,63)' has upper bits 0...01 where '0's symbolize sign bits of 'a' and 1 symbolizes its most significant non-sign bit.
  1139. 'shl 1' ensures storing the sign bit. }
  1140. result:=LengthUleb128(qword(a xor SarInt64(a,63)) shl 1);
  1141. end;
  1142. function EncodeUleb128(a: qword;out buf;len : byte) : byte;
  1143. var
  1144. b: byte;
  1145. pbuf : pbyte;
  1146. begin
  1147. result:=0;
  1148. pbuf:=@buf;
  1149. repeat
  1150. b := a and $7f;
  1151. a := a shr 7;
  1152. if a<>0 then
  1153. b := b or $80;
  1154. pbuf^:=b;
  1155. inc(pbuf);
  1156. inc(result);
  1157. until (a=0) and (result>=len);
  1158. end;
  1159. function EncodeSleb128(a: int64;out buf;len : byte) : byte;
  1160. var
  1161. b: byte;
  1162. more: boolean;
  1163. pbuf : pbyte;
  1164. begin
  1165. result:=0;
  1166. pbuf:=@buf;
  1167. repeat
  1168. b := a and $7f;
  1169. a := SarInt64(a, 7);
  1170. inc(result);
  1171. more:=(result<len) or (a<>-(b shr 6));
  1172. pbuf^:=b or byte(more) shl 7;
  1173. inc(pbuf);
  1174. until not more;
  1175. end;
  1176. initialization
  1177. internalerrorproc:=@defaulterror;
  1178. initupperlower;
  1179. end.