2
0

cutils.pas 45 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722
  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. function PadSpace(const s:string;len:longint):string;
  82. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  83. function GetToken(var s:string;endchar:char):string;
  84. procedure uppervar(var s : string);
  85. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  86. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  87. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  88. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  89. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  90. function DStr(l:longint):string;
  91. {# Returns true if the string s is a number }
  92. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  93. {# Returns true if value is a power of 2, the actual
  94. exponent value is returned in power.
  95. }
  96. function ispowerof2(value : int64;out power : longint) : boolean;
  97. function ispowerof2(const value : Tconstexprint;out power : longint) : boolean;
  98. {# Returns true if abs(value) is a power of 2, the actual
  99. exponent value is returned in power.
  100. }
  101. function isabspowerof2(const value : Tconstexprint;out power : longint) : boolean;
  102. function nextpowerof2(value : int64; out power: longint) : int64;
  103. {$ifdef VER2_6} { only 2.7.1+ has a popcnt function in the system unit }
  104. function PopCnt(AValue : Byte): Byte;
  105. function PopCnt(AValue : Word): Word;
  106. function PopCnt(AValue : DWord): DWord;
  107. function PopCnt(Const AValue : QWord): QWord;
  108. {$endif VER2_6}
  109. function backspace_quote(const s:string;const qchars:Tcharset):string;
  110. function octal_quote(const s:string;const qchars:Tcharset):string;
  111. {# If the string is quoted, in accordance with pascal, it is
  112. dequoted and returned in s, and the function returns true.
  113. If it is not quoted, or if the quoting is bad, s is not touched,
  114. and false is returned.
  115. }
  116. function DePascalQuote(var s: ansistring): Boolean;
  117. function CompareStr(const S1, S2: string): Integer;
  118. function CompareText(S1, S2: string): integer;
  119. function CompareVersionStrings(s1,s2: string): longint;
  120. { releases the string p and assignes nil to p }
  121. { if p=nil then freemem isn't called }
  122. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  123. { allocates mem for a copy of s, copies s to this mem and returns }
  124. { a pointer to this mem }
  125. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  126. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  127. {# Allocates memory for the string @var(s) and copies s as zero
  128. terminated string to that allocated memory and returns a pointer
  129. to that mem
  130. }
  131. function strpnew(const s : string) : pchar;
  132. function strpnew(const s : ansistring) : pchar;
  133. {# makes the character @var(c) lowercase, with spanish, french and german
  134. character set
  135. }
  136. function lowercase(c : char) : char;
  137. { makes zero terminated string to a pascal string }
  138. { the data in p is modified and p is returned }
  139. function pchar2pshortstring(p : pchar) : pshortstring;
  140. { inverse of pchar2pshortstring }
  141. function pshortstring2pchar(p : pshortstring) : pchar;
  142. { allocate a new pchar with the contents of a}
  143. function ansistring2pchar(const a: ansistring) : pchar;
  144. { Ansistring (pchar+length) support }
  145. procedure ansistringdispose(var p : pchar;length : longint);
  146. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  147. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  148. {Lzw encode/decode to compress strings -> save memory.}
  149. function minilzw_encode(const s:string):string;
  150. function minilzw_decode(const s:string):string;
  151. Function nextafter(x,y:double):double;
  152. function LengthUleb128(a: qword) : byte;
  153. function LengthSleb128(a: int64) : byte;
  154. function EncodeUleb128(a: qword;out buf;len: byte) : byte;
  155. function EncodeSleb128(a: int64;out buf;len: byte) : byte;
  156. { hide Sysutils.ExecuteProcess in units using this one after SysUtils}
  157. const
  158. ExecuteProcess = 'Do not use' deprecated 'Use cfileutil.RequotedExecuteProcess instead, ExecuteProcess cannot deal with single quotes as used by Unix command lines';
  159. implementation
  160. uses
  161. SysUtils;
  162. var
  163. uppertbl,
  164. lowertbl : array[char] of char;
  165. function min(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  166. {
  167. return the minimal of a and b
  168. }
  169. begin
  170. if a<=b then
  171. min:=a
  172. else
  173. min:=b;
  174. end;
  175. function min(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  176. {
  177. return the minimal of a and b
  178. }
  179. begin
  180. if a<=b then
  181. min:=a
  182. else
  183. min:=b;
  184. end;
  185. function min(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  186. {
  187. return the minimal of a and b
  188. }
  189. begin
  190. if a<=b then
  191. min:=a
  192. else
  193. min:=b;
  194. end;
  195. function min(a,b : qword) : qword;
  196. {
  197. return the minimal of a and b
  198. }
  199. begin
  200. if a<=b then
  201. min:=a
  202. else
  203. min:=b;
  204. end;
  205. function max(a,b : longint) : longint;{$ifdef USEINLINE}inline;{$endif}
  206. {
  207. return the maximum of a and b
  208. }
  209. begin
  210. if a>=b then
  211. max:=a
  212. else
  213. max:=b;
  214. end;
  215. function max(a,b : int64) : int64;{$ifdef USEINLINE}inline;{$endif}
  216. {
  217. return the maximum of a and b
  218. }
  219. begin
  220. if a>=b then
  221. max:=a
  222. else
  223. max:=b;
  224. end;
  225. function max(a,b : qword) : qword;{$ifdef USEINLINE}inline;{$endif}
  226. {
  227. return the maximum of a and b
  228. }
  229. begin
  230. if a>=b then
  231. max:=a
  232. else
  233. max:=b;
  234. end;
  235. function max(const a,b : Tconstexprint) : Tconstexprint;{$ifdef USEINLINE}inline;{$endif}
  236. {
  237. return the maximum of a and b
  238. }
  239. begin
  240. if a>=b then
  241. max:=a
  242. else
  243. max:=b;
  244. end;
  245. function newalignment(oldalignment: longint; offset: int64): longint;
  246. var
  247. localoffset: longint;
  248. begin
  249. localoffset:=longint(offset);
  250. while (localoffset mod oldalignment)<>0 do
  251. oldalignment:=oldalignment div 2;
  252. newalignment:=oldalignment;
  253. end;
  254. function reverse_byte(b: byte): byte;
  255. const
  256. reverse_nible:array[0..15] of 0..15 =
  257. (%0000,%1000,%0100,%1100,%0010,%1010,%0110,%1110,
  258. %0001,%1001,%0101,%1101,%0011,%1011,%0111,%1111);
  259. begin
  260. reverse_byte:=(reverse_nible[b and $f] shl 4) or reverse_nible[b shr 4];
  261. end;
  262. function reverse_word(w: word): word;
  263. type
  264. TWordRec = packed record
  265. hi, lo: Byte;
  266. end;
  267. begin
  268. TWordRec(reverse_word).hi := reverse_byte(TWordRec(w).lo);
  269. TWordRec(reverse_word).lo := reverse_byte(TWordRec(w).hi);
  270. end;
  271. function reverse_longword(l: longword): longword;
  272. type
  273. TLongWordRec = packed record
  274. b: array[0..3] of Byte;
  275. end;
  276. begin
  277. TLongWordRec(reverse_longword).b[0] := reverse_byte(TLongWordRec(l).b[3]);
  278. TLongWordRec(reverse_longword).b[1] := reverse_byte(TLongWordRec(l).b[2]);
  279. TLongWordRec(reverse_longword).b[2] := reverse_byte(TLongWordRec(l).b[1]);
  280. TLongWordRec(reverse_longword).b[3] := reverse_byte(TLongWordRec(l).b[0]);
  281. end;
  282. function align(i,a:longint):longint;{$ifdef USEINLINE}inline;{$endif}
  283. {
  284. return value <i> aligned <a> boundary
  285. }
  286. begin
  287. { for 0 and 1 no aligning is needed }
  288. if a<=1 then
  289. result:=i
  290. else
  291. begin
  292. if i<0 then
  293. result:=((i+1-a) div a) * a
  294. else
  295. result:=((i-1+a) div a) * a;
  296. end;
  297. end;
  298. function align(i,a:int64):int64;{$ifdef USEINLINE}inline;{$endif}
  299. {
  300. return value <i> aligned <a> boundary
  301. }
  302. begin
  303. { for 0 and 1 no aligning is needed }
  304. if a<=1 then
  305. result:=i
  306. else
  307. begin
  308. if i<0 then
  309. result:=((i+1-a) div a) * a
  310. else
  311. result:=((i-1+a) div a) * a;
  312. end;
  313. end;
  314. function align(i,a:qword):qword;{$ifdef USEINLINE}inline;{$endif}
  315. {
  316. return value <i> aligned <a> boundary
  317. }
  318. begin
  319. { for 0 and 1 no aligning is needed }
  320. if (a<=1) or (i=0) then
  321. result:=i
  322. else
  323. result:=((i-1+a) div a) * a;
  324. end;
  325. function packedbitsloadsize(bitlen: int64) : int64;
  326. begin
  327. case bitlen of
  328. 1,2,4,8:
  329. result := 1;
  330. { 10 bits can never be split over 3 bytes via 1-8-1, because it }
  331. { always starts at a multiple of 10 bits. Same for the others. }
  332. 3,5,6,7,9,10,12,16:
  333. result := 2;
  334. {$ifdef cpu64bitalu}
  335. { performance penalty for unaligned 8 byte access is much }
  336. { higher than for unaligned 4 byte access, at least on ppc, }
  337. { so use 4 bytes even in some cases where a value could }
  338. { always loaded using a single 8 byte load (e.g. in case of }
  339. { 28 bit values) }
  340. 11,13,14,15,17..32:
  341. result := 4;
  342. else
  343. result := 8;
  344. {$else cpu64bitalu}
  345. else
  346. result := 4;
  347. {$endif cpu64bitalu}
  348. end;
  349. end;
  350. function isbetteralignedthan(new, org, limit: cardinal): boolean;
  351. var
  352. cnt: cardinal;
  353. begin
  354. cnt:=2;
  355. while (cnt <= limit) do
  356. begin
  357. if (org and (cnt-1)) > (new and (cnt-1)) then
  358. begin
  359. result:=true;
  360. exit;
  361. end
  362. else if (org and (cnt-1)) < (new and (cnt-1)) then
  363. begin
  364. result:=false;
  365. exit;
  366. end;
  367. cnt:=cnt*2;
  368. end;
  369. result:=false;
  370. end;
  371. function next_prime(l: longint): longint;
  372. var
  373. check, checkbound: longint;
  374. ok: boolean;
  375. begin
  376. result:=l or 1;
  377. while l<high(longint) do
  378. begin
  379. ok:=true;
  380. checkbound:=trunc(sqrt(l));
  381. check:=3;
  382. while check<checkbound do
  383. begin
  384. if (l mod check) = 0 then
  385. begin
  386. ok:=false;
  387. break;
  388. end;
  389. inc(check,2);
  390. end;
  391. if ok then
  392. exit;
  393. inc(l);
  394. end;
  395. end;
  396. function used_align(varalign,minalign,maxalign:longint):longint;
  397. begin
  398. { varalign : minimum alignment required for the variable
  399. minalign : Minimum alignment of this structure, 0 = undefined
  400. maxalign : Maximum alignment of this structure, 0 = undefined }
  401. if (minalign>0) and
  402. (varalign<minalign) then
  403. used_align:=minalign
  404. else
  405. begin
  406. if (maxalign>0) and
  407. (varalign>maxalign) then
  408. used_align:=maxalign
  409. else
  410. used_align:=varalign;
  411. end;
  412. end;
  413. procedure Replace(var s:string;s1:string;const s2:string);
  414. var
  415. last,
  416. i : longint;
  417. begin
  418. s1:=upper(s1);
  419. last:=0;
  420. repeat
  421. i:=pos(s1,upper(s));
  422. if i=last then
  423. i:=0;
  424. if (i>0) then
  425. begin
  426. Delete(s,i,length(s1));
  427. Insert(s2,s,i);
  428. last:=i;
  429. end;
  430. until (i=0);
  431. end;
  432. procedure Replace(var s:AnsiString;s1:string;const s2:AnsiString);
  433. var
  434. last,
  435. i : longint;
  436. begin
  437. s1:=upper(s1);
  438. last:=0;
  439. repeat
  440. i:=pos(s1,upper(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:string;const s1,s2:string);
  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. procedure ReplaceCase(var s: ansistring; const s1, s2: ansistring);
  470. var
  471. last,
  472. i : longint;
  473. begin
  474. last:=0;
  475. repeat
  476. i:=pos(s1,s);
  477. if i=last then
  478. i:=0;
  479. if (i>0) then
  480. begin
  481. Delete(s,i,length(s1));
  482. Insert(s2,s,i);
  483. last:=i;
  484. end;
  485. until (i=0);
  486. end;
  487. Function MatchPattern(const pattern,what:string):boolean;
  488. var
  489. found : boolean;
  490. i1,i2 : longint;
  491. begin
  492. i1:=0;
  493. i2:=0;
  494. if pattern='' then
  495. begin
  496. result:=(what='');
  497. exit;
  498. end;
  499. found:=true;
  500. repeat
  501. inc(i1);
  502. if (i1>length(pattern)) then
  503. break;
  504. inc(i2);
  505. if (i2>length(what)) then
  506. break;
  507. case pattern[i1] of
  508. '?' :
  509. found:=true;
  510. '*' :
  511. begin
  512. found:=true;
  513. if (i1=length(pattern)) then
  514. i2:=length(what)
  515. else
  516. if (i1<length(pattern)) and (pattern[i1+1]<>what[i2]) then
  517. begin
  518. if i2<length(what) then
  519. dec(i1)
  520. end
  521. else
  522. if i2>1 then
  523. dec(i2);
  524. end;
  525. else
  526. found:=(pattern[i1]=what[i2]) or (what[i2]='?');
  527. end;
  528. until not found;
  529. if found then
  530. begin
  531. found:=(i2>=length(what)) and
  532. (
  533. (i1>length(pattern)) or
  534. ((i1=length(pattern)) and
  535. (pattern[i1]='*'))
  536. );
  537. end;
  538. result:=found;
  539. end;
  540. function upper(const c : char) : char;
  541. {
  542. return uppercase of c
  543. }
  544. begin
  545. upper:=uppertbl[c];
  546. end;
  547. function upper(const s : string) : string;
  548. {
  549. return uppercased string of s
  550. }
  551. var
  552. i : longint;
  553. begin
  554. for i:=1 to length(s) do
  555. upper[i]:=uppertbl[s[i]];
  556. upper[0]:=s[0];
  557. end;
  558. function upper(const s : ansistring) : ansistring;
  559. {
  560. return uppercased string of s
  561. }
  562. var
  563. i : longint;
  564. begin
  565. Result:='';
  566. setlength(upper,length(s));
  567. for i:=1 to length(s) do
  568. upper[i]:=uppertbl[s[i]];
  569. end;
  570. function lower(const c : char) : char;
  571. {
  572. return lowercase of c
  573. }
  574. begin
  575. lower:=lowertbl[c];
  576. end;
  577. function lower(const s : string) : string;
  578. {
  579. return lowercased string of s
  580. }
  581. var
  582. i : longint;
  583. begin
  584. for i:=1 to length(s) do
  585. lower[i]:=lowertbl[s[i]];
  586. lower[0]:=s[0];
  587. end;
  588. function lower(const s : ansistring) : ansistring;
  589. {
  590. return lowercased string of s
  591. }
  592. var
  593. i : longint;
  594. begin
  595. Result:='';
  596. setlength(lower,length(s));
  597. for i:=1 to length(s) do
  598. lower[i]:=lowertbl[s[i]];
  599. end;
  600. procedure uppervar(var s : string);
  601. {
  602. uppercase string s
  603. }
  604. var
  605. i : longint;
  606. begin
  607. for i:=1 to length(s) do
  608. s[i]:=uppertbl[s[i]];
  609. end;
  610. procedure initupperlower;
  611. var
  612. c : char;
  613. begin
  614. for c:=#0 to #255 do
  615. begin
  616. lowertbl[c]:=c;
  617. uppertbl[c]:=c;
  618. case c of
  619. 'A'..'Z' :
  620. lowertbl[c]:=char(byte(c)+32);
  621. 'a'..'z' :
  622. uppertbl[c]:=char(byte(c)-32);
  623. end;
  624. end;
  625. end;
  626. function DStr(l:longint):string;
  627. var
  628. TmpStr : string[32];
  629. i : longint;
  630. begin
  631. Str(l,TmpStr);
  632. i:=Length(TmpStr);
  633. while (i>3) do
  634. begin
  635. dec(i,3);
  636. if TmpStr[i]<>'-' then
  637. insert('.',TmpStr,i+1);
  638. end;
  639. DStr:=TmpStr;
  640. end;
  641. function rpos(const needle: char; const haystack: shortstring): longint;
  642. begin
  643. result:=length(haystack);
  644. while (result>0) do
  645. begin
  646. if haystack[result]=needle then
  647. exit;
  648. dec(result);
  649. end;
  650. end;
  651. function rpos(const needle: shortstring; const haystack: shortstring): longint;
  652. begin
  653. result:=0;
  654. if (length(needle)=0) or
  655. (length(needle)>length(haystack)) then
  656. exit;
  657. result:=length(haystack)-length(needle);
  658. repeat
  659. if (haystack[result]=needle[1]) and
  660. (copy(haystack,result,length(needle))=needle) then
  661. exit;
  662. dec(result);
  663. until result=0;
  664. end;
  665. function trimspace(const s:string):string;
  666. {
  667. return s with all leading and ending spaces and tabs removed
  668. }
  669. var
  670. i,j : longint;
  671. begin
  672. i:=length(s);
  673. while (i>0) and (s[i] in [#9,' ']) do
  674. dec(i);
  675. j:=1;
  676. while (j<i) and (s[j] in [#9,' ']) do
  677. inc(j);
  678. trimspace:=Copy(s,j,i-j+1);
  679. end;
  680. function trimspace(const s:AnsiString):AnsiString;
  681. {
  682. return s with all leading and ending spaces and tabs removed
  683. }
  684. var
  685. i,j : longint;
  686. begin
  687. i:=length(s);
  688. while (i>0) and (s[i] in [#9,' ']) do
  689. dec(i);
  690. j:=1;
  691. while (j<i) and (s[j] in [#9,' ']) do
  692. inc(j);
  693. trimspace:=Copy(s,j,i-j+1);
  694. end;
  695. function space (b : longint): string;
  696. var
  697. s: string;
  698. begin
  699. space[0] := chr(b);
  700. s[0] := chr(b);
  701. FillChar (S[1],b,' ');
  702. space:=s;
  703. end;
  704. function PadSpace(const s:string;len:longint):string;
  705. {
  706. return s with spaces add to the end
  707. }
  708. begin
  709. if length(s)<len then
  710. PadSpace:=s+Space(len-length(s))
  711. else
  712. PadSpace:=s;
  713. end;
  714. function PadSpace(const s:AnsiString;len:longint):AnsiString;
  715. {
  716. return s with spaces add to the end
  717. }
  718. begin
  719. if length(s)<len then
  720. PadSpace:=s+Space(len-length(s))
  721. else
  722. PadSpace:=s;
  723. end;
  724. function GetToken(var s:string;endchar:char):string;
  725. var
  726. i : longint;
  727. quote : char;
  728. begin
  729. GetToken:='';
  730. s:=TrimSpace(s);
  731. if (length(s)>0) and
  732. (s[1] in ['''','"']) then
  733. begin
  734. quote:=s[1];
  735. i:=1;
  736. while (i<length(s)) do
  737. begin
  738. inc(i);
  739. if s[i]=quote then
  740. begin
  741. { Remove double quote }
  742. if (i<length(s)) and
  743. (s[i+1]=quote) then
  744. begin
  745. Delete(s,i,1);
  746. inc(i);
  747. end
  748. else
  749. begin
  750. GetToken:=Copy(s,2,i-2);
  751. Delete(s,1,i);
  752. exit;
  753. end;
  754. end;
  755. end;
  756. GetToken:=s;
  757. s:='';
  758. end
  759. else
  760. begin
  761. i:=pos(EndChar,s);
  762. if i=0 then
  763. begin
  764. GetToken:=s;
  765. s:='';
  766. exit;
  767. end
  768. else
  769. begin
  770. GetToken:=Copy(s,1,i-1);
  771. Delete(s,1,i);
  772. exit;
  773. end;
  774. end;
  775. end;
  776. function realtostr(e:extended):string;{$ifdef USEINLINE}inline;{$endif}
  777. begin
  778. str(e,result);
  779. end;
  780. function tostr(i : qword) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  781. {
  782. return string of value i
  783. }
  784. begin
  785. str(i,result);
  786. end;
  787. function tostr(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  788. {
  789. return string of value i
  790. }
  791. begin
  792. str(i,result);
  793. end;
  794. function tostr(i : longint) : string;{$ifdef USEINLINE}inline;{$endif}overload;
  795. {
  796. return string of value i
  797. }
  798. begin
  799. str(i,result);
  800. end;
  801. function tostr_with_plus(i : int64) : string;{$ifdef USEINLINE}inline;{$endif}
  802. {
  803. return string of value i, but always include a + when i>=0
  804. }
  805. begin
  806. str(i,result);
  807. if i>=0 then
  808. result:='+'+result;
  809. end;
  810. function is_number(const s : string) : boolean;{$ifdef USEINLINE}inline;{$endif}
  811. {
  812. is string a correct number ?
  813. }
  814. var
  815. w : integer;
  816. l : longint;
  817. begin
  818. val(s,l,w);
  819. // remove warning
  820. l:=l;
  821. is_number:=(w=0);
  822. end;
  823. function ispowerof2(value : int64;out power : longint) : boolean;
  824. {
  825. return if value is a power of 2. And if correct return the power
  826. }
  827. begin
  828. if (value <= 0) or (value and (value - 1) <> 0) then
  829. exit(false);
  830. power:=BsfQWord(value);
  831. result:=true;
  832. end;
  833. function ispowerof2(const value: Tconstexprint; out power: longint): boolean;
  834. begin
  835. if value.signed or
  836. (value.uvalue<=high(int64)) then
  837. result:=ispowerof2(value.svalue,power)
  838. else if not value.signed and
  839. (value.svalue=low(int64)) then
  840. begin
  841. result:=true;
  842. power:=63;
  843. end
  844. else
  845. result:=false;
  846. end;
  847. function isabspowerof2(const value : Tconstexprint;out power : longint) : boolean;
  848. begin
  849. if ispowerof2(value,power) then
  850. result:=true
  851. else if value.signed and (value.svalue<0) and (value.svalue<>low(int64)) and ispowerof2(-value.svalue,power) then
  852. result:=true
  853. else
  854. result:=false;
  855. end;
  856. function nextpowerof2(value : int64; out power: longint) : int64;
  857. {
  858. returns the power of 2 >= value
  859. }
  860. var
  861. i : longint;
  862. begin
  863. result := 0;
  864. power := -1;
  865. if ((value <= 0) or
  866. (value >= $4000000000000000)) then
  867. exit;
  868. result := 1;
  869. for i:=0 to 63 do
  870. begin
  871. if result>=value then
  872. begin
  873. power := i;
  874. exit;
  875. end;
  876. result:=result shl 1;
  877. end;
  878. end;
  879. {$ifdef VER2_6}
  880. const
  881. PopCntData : array[0..15] of byte = (0,1,1,2,1,2,2,3,1,2,2,3,2,3,3,4);
  882. function PopCnt(AValue : Byte): Byte;
  883. begin
  884. Result:=PopCntData[AValue and $f]+PopCntData[(AValue shr 4) and $f];
  885. end;
  886. function PopCnt(AValue : Word): Word;
  887. var
  888. i : SizeInt;
  889. begin
  890. Result:=0;
  891. for i:=0 to 3 do
  892. begin
  893. inc(Result,PopCntData[AValue and $f]);
  894. AValue:=AValue shr 4;
  895. end;
  896. end;
  897. function PopCnt(AValue : DWord): DWord;
  898. var
  899. i : SizeInt;
  900. begin
  901. Result:=0;
  902. for i:=0 to 7 do
  903. begin
  904. inc(Result,PopCntData[AValue and $f]);
  905. AValue:=AValue shr 4;
  906. end;
  907. end;
  908. function PopCnt(Const AValue : QWord): QWord;
  909. begin
  910. Result:=PopCnt(lo(AValue))+PopCnt(hi(AValue))
  911. end;
  912. {$endif VER2_6}
  913. function backspace_quote(const s:string;const qchars:Tcharset):string;
  914. var i:byte;
  915. begin
  916. backspace_quote:='';
  917. for i:=1 to length(s) do
  918. begin
  919. if (s[i]=#10) and (#10 in qchars) then
  920. backspace_quote:=backspace_quote+'\n'
  921. else if (s[i]=#13) and (#13 in qchars) then
  922. backspace_quote:=backspace_quote+'\r'
  923. else
  924. begin
  925. if s[i] in qchars then
  926. backspace_quote:=backspace_quote+'\';
  927. backspace_quote:=backspace_quote+s[i];
  928. end;
  929. end;
  930. end;
  931. function octal_quote(const s:string;const qchars:Tcharset):string;
  932. var i:byte;
  933. begin
  934. octal_quote:='';
  935. for i:=1 to length(s) do
  936. begin
  937. if s[i] in qchars then
  938. begin
  939. if ord(s[i])<64 then
  940. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),3)
  941. else
  942. octal_quote:=octal_quote+'\'+octstr(ord(s[i]),4);
  943. end
  944. else
  945. octal_quote:=octal_quote+s[i];
  946. end;
  947. end;
  948. function DePascalQuote(var s: ansistring): Boolean;
  949. var
  950. destPos, sourcePos, len: Integer;
  951. t: string;
  952. ch: Char;
  953. begin
  954. t:='';
  955. DePascalQuote:= false;
  956. len:= length(s);
  957. if (len >= 1) and (s[1] = '''') then
  958. begin
  959. {Remove quotes, exchange '' against ' }
  960. destPos := 0;
  961. sourcepos:=1;
  962. while (sourcepos<len) do
  963. begin
  964. inc(sourcePos);
  965. ch := s[sourcePos];
  966. if ch = '''' then
  967. begin
  968. inc(sourcePos);
  969. if (sourcePos <= len) and (s[sourcePos] = '''') then
  970. {Add the quote as part of string}
  971. else
  972. begin
  973. SetLength(t, destPos);
  974. s:= t;
  975. Exit(true);
  976. end;
  977. end;
  978. inc(destPos);
  979. t[destPos] := ch;
  980. end;
  981. end;
  982. end;
  983. function pchar2pshortstring(p : pchar) : pshortstring;
  984. var
  985. w,i : longint;
  986. begin
  987. w:=strlen(p);
  988. for i:=w-1 downto 0 do
  989. p[i+1]:=p[i];
  990. p[0]:=chr(w);
  991. pchar2pshortstring:=pshortstring(p);
  992. end;
  993. function pshortstring2pchar(p : pshortstring) : pchar;
  994. var
  995. w,i : longint;
  996. begin
  997. w:=length(p^);
  998. for i:=1 to w do
  999. p^[i-1]:=p^[i];
  1000. p^[w]:=#0;
  1001. pshortstring2pchar:=pchar(p);
  1002. end;
  1003. function ansistring2pchar(const a: ansistring) : pchar;
  1004. var
  1005. len: ptrint;
  1006. begin
  1007. len:=length(a);
  1008. getmem(result,len+1);
  1009. if (len<>0) then
  1010. move(a[1],result[0],len);
  1011. result[len]:=#0;
  1012. end;
  1013. function lowercase(c : char) : char;
  1014. begin
  1015. case c of
  1016. #65..#90 : c := chr(ord (c) + 32);
  1017. #154 : c:=#129; { german }
  1018. #142 : c:=#132; { german }
  1019. #153 : c:=#148; { german }
  1020. #144 : c:=#130; { french }
  1021. #128 : c:=#135; { french }
  1022. #143 : c:=#134; { swedish/norge (?) }
  1023. #165 : c:=#164; { spanish }
  1024. #228 : c:=#229; { greek }
  1025. #226 : c:=#231; { greek }
  1026. #232 : c:=#227; { greek }
  1027. end;
  1028. lowercase := c;
  1029. end;
  1030. function strpnew(const s : string) : pchar;
  1031. var
  1032. p : pchar;
  1033. begin
  1034. getmem(p,length(s)+1);
  1035. move(s[1],p^,length(s));
  1036. p[length(s)]:=#0;
  1037. result:=p;
  1038. end;
  1039. function strpnew(const s: ansistring): pchar;
  1040. var
  1041. p : pchar;
  1042. begin
  1043. getmem(p,length(s)+1);
  1044. move(s[1],p^,length(s)+1);
  1045. result:=p;
  1046. end;
  1047. procedure stringdispose(var p : pshortstring);{$ifdef USEINLINE}inline;{$endif}
  1048. begin
  1049. if assigned(p) then
  1050. begin
  1051. freemem(p);
  1052. p:=nil;
  1053. end;
  1054. end;
  1055. function stringdup(const s : shortstring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1056. begin
  1057. getmem(result,length(s)+1);
  1058. result^:=s;
  1059. end;
  1060. function stringdup(const s : ansistring) : pshortstring;{$ifdef USEINLINE}inline;{$endif}
  1061. begin
  1062. getmem(result,length(s)+1);
  1063. result^:=s;
  1064. end;
  1065. function CompareStr(const S1, S2: string): Integer;
  1066. var
  1067. count, count1, count2: integer;
  1068. begin
  1069. result := 0;
  1070. Count1 := Length(S1);
  1071. Count2 := Length(S2);
  1072. if Count1>Count2 then
  1073. Count:=Count2
  1074. else
  1075. Count:=Count1;
  1076. result := CompareChar(S1[1],S2[1], Count);
  1077. if result=0 then
  1078. result:=Count1-Count2;
  1079. end;
  1080. function CompareText(S1, S2: string): integer;
  1081. begin
  1082. UpperVar(S1);
  1083. UpperVar(S2);
  1084. Result:=CompareStr(S1,S2);
  1085. end;
  1086. function CompareVersionStrings(s1,s2: string): longint;
  1087. var
  1088. start1, start2,
  1089. i1, i2,
  1090. num1,num2,
  1091. res,
  1092. err : longint;
  1093. begin
  1094. i1:=1;
  1095. i2:=1;
  1096. repeat
  1097. start1:=i1;
  1098. start2:=i2;
  1099. while (i1<=length(s1)) and
  1100. (s1[i1] in ['0'..'9']) do
  1101. inc(i1);
  1102. while (i2<=length(s2)) and
  1103. (s2[i2] in ['0'..'9']) do
  1104. inc(i2);
  1105. { one of the strings misses digits -> other is the largest version }
  1106. if i1=start1 then
  1107. if i2=start2 then
  1108. exit(0)
  1109. else
  1110. exit(-1)
  1111. else if i2=start2 then
  1112. exit(1);
  1113. { get version number part }
  1114. val(copy(s1,start1,i1-start1),num1,err);
  1115. val(copy(s2,start2,i2-start2),num2,err);
  1116. { different -> done }
  1117. res:=num1-num2;
  1118. if res<>0 then
  1119. exit(res);
  1120. { if one of the two is at the end while the other isn't, add a '.0' }
  1121. if (i1>length(s1)) and
  1122. (i2<=length(s2)) then
  1123. s1:=s1+'.0';
  1124. if (i2>length(s2)) and
  1125. (i1<=length(s1)) then
  1126. s2:=s2+'.0';
  1127. { compare non-numerical characters normally }
  1128. while (i1<=length(s1)) and
  1129. not(s1[i1] in ['0'..'9']) and
  1130. (i2<=length(s2)) and
  1131. not(s2[i2] in ['0'..'9']) do
  1132. begin
  1133. res:=ord(s1[i1])-ord(s2[i2]);
  1134. if res<>0 then
  1135. exit(res);
  1136. inc(i1);
  1137. inc(i2);
  1138. end;
  1139. { both should be digits again now, otherwise pick the one with the
  1140. digits as the largest (it more likely means that the input was
  1141. ill-formatted though) }
  1142. if (i1<=length(s1)) and
  1143. not(s1[i1] in ['0'..'9']) then
  1144. exit(-1);
  1145. if (i2<=length(s2)) and
  1146. not(s2[i2] in ['0'..'9']) then
  1147. exit(1);
  1148. until false;
  1149. end;
  1150. {*****************************************************************************
  1151. Ansistring (PChar+Length)
  1152. *****************************************************************************}
  1153. procedure ansistringdispose(var p : pchar;length : longint);
  1154. begin
  1155. if assigned(p) then
  1156. begin
  1157. freemem(p);
  1158. p:=nil;
  1159. end;
  1160. end;
  1161. { enable ansistring comparison }
  1162. { 0 means equal }
  1163. { 1 means p1 > p2 }
  1164. { -1 means p1 < p2 }
  1165. function compareansistrings(p1,p2 : pchar;length1,length2 : longint) : longint;
  1166. var
  1167. i,j : longint;
  1168. begin
  1169. compareansistrings:=0;
  1170. j:=min(length1,length2);
  1171. i:=0;
  1172. while (i<j) do
  1173. begin
  1174. if p1[i]>p2[i] then
  1175. begin
  1176. compareansistrings:=1;
  1177. exit;
  1178. end
  1179. else
  1180. if p1[i]<p2[i] then
  1181. begin
  1182. compareansistrings:=-1;
  1183. exit;
  1184. end;
  1185. inc(i);
  1186. end;
  1187. if length1>length2 then
  1188. compareansistrings:=1
  1189. else
  1190. if length1<length2 then
  1191. compareansistrings:=-1;
  1192. end;
  1193. function concatansistrings(p1,p2 : pchar;length1,length2 : longint) : pchar;
  1194. var
  1195. p : pchar;
  1196. begin
  1197. getmem(p,length1+length2+1);
  1198. move(p1[0],p[0],length1);
  1199. move(p2[0],p[length1],length2+1);
  1200. concatansistrings:=p;
  1201. end;
  1202. {*****************************************************************************
  1203. Ultra basic KISS Lzw (de)compressor
  1204. *****************************************************************************}
  1205. {This is an extremely basic implementation of the Lzw algorithm. It
  1206. compresses 7-bit ASCII strings into 8-bit compressed strings.
  1207. The Lzw dictionary is preinitialized with 0..127, therefore this
  1208. part of the dictionary does not need to be stored in the arrays.
  1209. The Lzw code size is allways 8 bit, so we do not need complex code
  1210. that can write partial bytes.}
  1211. function minilzw_encode(const s:string):string;
  1212. var t,u,i:byte;
  1213. c:char;
  1214. data:array[128..255] of char;
  1215. previous:array[128..255] of byte;
  1216. lzwptr:byte;
  1217. next_avail:set of 0..255;
  1218. label l1;
  1219. begin
  1220. minilzw_encode:='';
  1221. fillchar(data,sizeof(data),#0);
  1222. fillchar(previous,sizeof(previous),#0);
  1223. if s<>'' then
  1224. begin
  1225. lzwptr:=127;
  1226. t:=byte(s[1]);
  1227. i:=2;
  1228. u:=128;
  1229. next_avail:=[];
  1230. while i<=length(s) do
  1231. begin
  1232. c:=s[i];
  1233. if not(t in next_avail) or (u>lzwptr) then goto l1;
  1234. while (previous[u]<>t) or (data[u]<>c) do
  1235. begin
  1236. inc(u);
  1237. if u>lzwptr then goto l1;
  1238. end;
  1239. t:=u;
  1240. inc(i);
  1241. continue;
  1242. l1:
  1243. {It's a pity that we still need those awfull tricks
  1244. with this modern compiler. Without this performance
  1245. of the entire procedure drops about 3 times.}
  1246. inc(minilzw_encode[0]);
  1247. minilzw_encode[length(minilzw_encode)]:=char(t);
  1248. if lzwptr=255 then
  1249. begin
  1250. lzwptr:=127;
  1251. next_avail:=[];
  1252. end
  1253. else
  1254. begin
  1255. inc(lzwptr);
  1256. data[lzwptr]:=c;
  1257. previous[lzwptr]:=t;
  1258. include(next_avail,t);
  1259. end;
  1260. t:=byte(c);
  1261. u:=128;
  1262. inc(i);
  1263. end;
  1264. inc(minilzw_encode[0]);
  1265. minilzw_encode[length(minilzw_encode)]:=char(t);
  1266. end;
  1267. end;
  1268. function minilzw_decode(const s:string):string;
  1269. var oldc,newc,c:char;
  1270. i,j:byte;
  1271. data:array[128..255] of char;
  1272. previous:array[128..255] of byte;
  1273. lzwptr:byte;
  1274. t:string;
  1275. begin
  1276. minilzw_decode:='';
  1277. fillchar(data,sizeof(data),#0);
  1278. fillchar(previous,sizeof(previous),#0);
  1279. if s<>'' then
  1280. begin
  1281. lzwptr:=127;
  1282. oldc:=s[1];
  1283. c:=oldc;
  1284. i:=2;
  1285. minilzw_decode:=oldc;
  1286. while i<=length(s) do
  1287. begin
  1288. newc:=s[i];
  1289. if byte(newc)>lzwptr then
  1290. begin
  1291. t:=c;
  1292. c:=oldc;
  1293. end
  1294. else
  1295. begin
  1296. c:=newc;
  1297. t:='';
  1298. end;
  1299. while c>=#128 do
  1300. begin
  1301. inc(t[0]);
  1302. t[length(t)]:=data[byte(c)];
  1303. byte(c):=previous[byte(c)];
  1304. end;
  1305. inc(minilzw_decode[0]);
  1306. minilzw_decode[length(minilzw_decode)]:=c;
  1307. for j:=length(t) downto 1 do
  1308. begin
  1309. inc(minilzw_decode[0]);
  1310. minilzw_decode[length(minilzw_decode)]:=t[j];
  1311. end;
  1312. if lzwptr=255 then
  1313. lzwptr:=127
  1314. else
  1315. begin
  1316. inc(lzwptr);
  1317. previous[lzwptr]:=byte(oldc);
  1318. data[lzwptr]:=c;
  1319. end;
  1320. oldc:=newc;
  1321. inc(i);
  1322. end;
  1323. end;
  1324. end;
  1325. procedure defaulterror(i:longint);
  1326. begin
  1327. writeln('Internal error ',i);
  1328. runerror(255);
  1329. end;
  1330. Function Nextafter(x,y:double):double;
  1331. // Returns the double precision number closest to x in
  1332. // the direction toward y.
  1333. // Initial direct translation by Soeren Haastrup from
  1334. // www.netlib.org/fdlibm/s_nextafter.c according to
  1335. // ====================================================
  1336. // Copyright (C) 1993 by Sun Microsystems, Inc. All rights reserved.
  1337. // Developed at SunSoft, a Sun Microsystems, Inc. business.
  1338. // Permission to use, copy, modify, and distribute this
  1339. // software is freely granted, provided that this notice
  1340. // is preserved.
  1341. // ====================================================
  1342. // and with all signaling policies preserved as is.
  1343. type
  1344. {$if defined(ENDIAN_LITTLE) and not defined(FPC_DOUBLE_HILO_SWAPPED)}
  1345. twoword=record
  1346. lo,hi:longword; // Little Endian split of a double.
  1347. end;
  1348. {$else}
  1349. twoword=record
  1350. hi,lo:longword; // Big Endian split of a double.
  1351. end;
  1352. {$endif}
  1353. var
  1354. hx,hy,ix,iy:longint;
  1355. lx,ly:longword;
  1356. Begin
  1357. hx:=twoword(x).hi; // high and low words of x and y
  1358. lx:=twoword(x).lo;
  1359. hy:=twoword(y).hi;
  1360. ly:=twoword(y).lo;
  1361. ix:=hx and $7fffffff; // absolute values
  1362. iy:=hy and $7fffffff;
  1363. // Case x=NAN or y=NAN
  1364. if ( (ix>=$7ff00000) and ((longword(ix-$7ff00000) or lx) <> 0) )
  1365. or ( (iy>=$7ff00000) and ((longword(iy-$7ff00000) OR ly) <> 0) )
  1366. then exit(x+y);
  1367. // Case x=y
  1368. if x=y then exit(x); // (implies Nextafter(0,-0) is 0 and not -0...)
  1369. // Case x=0
  1370. if (longword(ix) or lx)=0
  1371. then begin
  1372. twoword(x).hi:=hy and $80000000; // return +-minimalSubnormal
  1373. twoword(x).lo:=1;
  1374. y:=x*x; // set underflow flag (ignored in FPC as default)
  1375. if y=x
  1376. then exit(y)
  1377. else exit(x);
  1378. end;
  1379. // all other cases
  1380. if hx>=0 // x>0
  1381. then begin
  1382. if (hx>hy) or ( (hx=hy) and (lx>ly) ) // x>y , return x-ulp
  1383. then begin
  1384. if (lx=0) then hx:=hx-1;
  1385. lx:=lx-1;
  1386. end
  1387. else begin // x<y, return x+ulp
  1388. lx:=lx+1;
  1389. if lx=0 then hx:=hx+1;
  1390. end
  1391. end
  1392. else begin // x<0
  1393. if (hy>=0) or (hx>=hy) or ( (hx=hy) and (lx>ly)) // x<y, return x-ulp
  1394. then begin
  1395. if (lx=0) then hx:=hx-1;
  1396. lx:=lx-1;
  1397. end
  1398. else begin // x>y , return x+ulp
  1399. lx:=lx+1;
  1400. if lx=0 then hx:=hx+1;
  1401. end
  1402. end;
  1403. // finally check if overflow or underflow just happend
  1404. hy:=hx and $7ff00000;
  1405. if (hy>= $7ff00000) then exit(x+x); // overflow and signal
  1406. if (hy<$0010000) // underflow
  1407. then begin
  1408. y:=x*x; // raise underflow flag
  1409. if y<>x
  1410. then begin
  1411. twoword(y).hi:=hx;
  1412. twoword(y).lo:=lx;
  1413. exit(y);
  1414. end
  1415. end;
  1416. twoword(x).hi:=hx;
  1417. twoword(x).lo:=lx;
  1418. nextafter:=x;
  1419. end;
  1420. function LengthUleb128(a: qword) : byte;
  1421. begin
  1422. result:=0;
  1423. repeat
  1424. a := a shr 7;
  1425. inc(result);
  1426. if a=0 then
  1427. break;
  1428. until false;
  1429. end;
  1430. function LengthSleb128(a: int64) : byte;
  1431. var
  1432. b: byte;
  1433. more: boolean;
  1434. begin
  1435. more := true;
  1436. result:=0;
  1437. repeat
  1438. b := a and $7f;
  1439. a := SarInt64(a, 7);
  1440. if (
  1441. ((a = 0) and (b and $40 = 0)) or
  1442. ((a = -1) and (b and $40 <> 0))
  1443. ) then
  1444. more := false;
  1445. inc(result);
  1446. if not(more) then
  1447. break;
  1448. until false;
  1449. end;
  1450. function EncodeUleb128(a: qword;out buf;len : byte) : byte;
  1451. var
  1452. b: byte;
  1453. pbuf : pbyte;
  1454. begin
  1455. result:=0;
  1456. pbuf:=@buf;
  1457. repeat
  1458. b := a and $7f;
  1459. a := a shr 7;
  1460. if a<>0 then
  1461. b := b or $80;
  1462. pbuf^:=b;
  1463. inc(pbuf);
  1464. inc(result);
  1465. if (a=0) and (result>=len) then
  1466. break;
  1467. until false;
  1468. end;
  1469. function EncodeSleb128(a: int64;out buf;len : byte) : byte;
  1470. var
  1471. b: byte;
  1472. more: boolean;
  1473. pbuf : pbyte;
  1474. begin
  1475. more := true;
  1476. result:=0;
  1477. pbuf:=@buf;
  1478. repeat
  1479. b := a and $7f;
  1480. a := SarInt64(a, 7);
  1481. if (result+1>=len) and (
  1482. ((a = 0) and (b and $40 = 0)) or
  1483. ((a = -1) and (b and $40 <> 0))
  1484. ) then
  1485. more := false
  1486. else
  1487. b := b or $80;
  1488. pbuf^:=b;
  1489. inc(pbuf);
  1490. inc(result);
  1491. until not more;
  1492. end;
  1493. initialization
  1494. internalerrorproc:=@defaulterror;
  1495. initupperlower;
  1496. end.