cobjects.pas 60 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399
  1. {
  2. $Id$
  3. Copyright (c) 1998-2000 by Florian Klaempfl
  4. This module provides some basic objects
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. {$ifdef tp}
  19. {$E+,N+,D+,F+}
  20. {$endif}
  21. {$I-}
  22. {$R-}{ necessary for crc calculation }
  23. unit cobjects;
  24. { define OLDSPEEDVALUE}
  25. interface
  26. uses
  27. {$ifdef DELPHI4}
  28. dmisc,
  29. sysutils
  30. {$else DELPHI4}
  31. strings
  32. {$ifndef linux}
  33. ,dos
  34. {$else}
  35. ,linux
  36. {$endif}
  37. {$endif DELPHI4}
  38. ;
  39. const
  40. { the real size will be [-hasharray..hasharray] ! }
  41. {$ifdef TP}
  42. hasharraysize = 127;
  43. {$else}
  44. hasharraysize = 2047;
  45. {$endif}
  46. type
  47. pstring = ^string;
  48. {$ifdef TP}
  49. { redeclare dword only in case of emergency, some small things
  50. of the compiler won't work then correctly (FK)
  51. }
  52. dword = longint;
  53. {$endif TP}
  54. pfileposinfo = ^tfileposinfo;
  55. tfileposinfo = record
  56. line : longint;
  57. column : word;
  58. fileindex : word;
  59. end;
  60. pmemdebug = ^tmemdebug;
  61. tmemdebug = object
  62. constructor init(const s:string);
  63. destructor done;
  64. procedure show;
  65. private
  66. startmem : longint;
  67. infostr : string[40];
  68. end;
  69. plinkedlist_item = ^tlinkedlist_item;
  70. tlinkedlist_item = object
  71. next,previous : plinkedlist_item;
  72. { does nothing }
  73. constructor init;
  74. destructor done;virtual;
  75. function getcopy:plinkedlist_item;virtual;
  76. end;
  77. pstring_item = ^tstring_item;
  78. tstring_item = object(tlinkedlist_item)
  79. str : pstring;
  80. constructor init(const s : string);
  81. destructor done;virtual;
  82. end;
  83. { this implements a double linked list }
  84. plinkedlist = ^tlinkedlist;
  85. tlinkedlist = object
  86. first,last : plinkedlist_item;
  87. constructor init;
  88. destructor done;
  89. { destructors the linkedlist without cleaning the items up }
  90. destructor done_noclear;
  91. { disposes the items of the list }
  92. procedure clear;
  93. { concats a new item at the end }
  94. procedure concat(p : plinkedlist_item);
  95. { inserts a new item at the begin }
  96. procedure insert(p : plinkedlist_item);
  97. { inserts another list at the begin and make this list empty }
  98. procedure insertlist(p : plinkedlist);
  99. { concats another list at the end and make this list empty }
  100. procedure concatlist(p : plinkedlist);
  101. procedure concatlistcopy(p : plinkedlist);
  102. { removes p from the list (p isn't disposed) }
  103. { it's not tested if p is in the list ! }
  104. procedure remove(p : plinkedlist_item);
  105. { is the linkedlist empty ? }
  106. function empty:boolean;
  107. { items in the list }
  108. function count:longint;
  109. end;
  110. { some help data types }
  111. pstringqueueitem = ^tstringqueueitem;
  112. tstringqueueitem = object
  113. data : pstring;
  114. next : pstringqueueitem;
  115. end;
  116. { String Queue}
  117. PStringQueue=^TStringQueue;
  118. TStringQueue=object
  119. first,last : PStringqueueItem;
  120. constructor Init;
  121. destructor Done;
  122. function Empty:boolean;
  123. function Get:string;
  124. function Find(const s:string):PStringqueueItem;
  125. function Delete(const s:string):boolean;
  126. procedure Insert(const s:string);
  127. procedure Concat(const s:string);
  128. procedure Clear;
  129. end;
  130. { containeritem }
  131. pcontaineritem = ^tcontaineritem;
  132. tcontaineritem = object
  133. next : pcontaineritem;
  134. constructor init;
  135. destructor done;virtual;
  136. end;
  137. { container }
  138. pcontainer = ^tcontainer;
  139. tcontainer = object
  140. root,
  141. last : pcontaineritem;
  142. constructor init;
  143. destructor done;
  144. { true when the container is empty }
  145. function empty:boolean;
  146. { inserts a string }
  147. procedure insert(item:pcontaineritem);
  148. { gets a string }
  149. function get:pcontaineritem;
  150. { deletes all items }
  151. procedure clear;
  152. end;
  153. { containeritem }
  154. pstringcontaineritem = ^tstringcontaineritem;
  155. tstringcontaineritem = object(tcontaineritem)
  156. data : pstring;
  157. file_info : tfileposinfo;
  158. constructor init(const s:string);
  159. constructor Init_TokenInfo(const s:string;const pos:tfileposinfo);
  160. destructor done;virtual;
  161. end;
  162. { string container }
  163. pstringcontainer = ^tstringcontainer;
  164. tstringcontainer = object(tcontainer)
  165. doubles : boolean; { if this is set to true, doubles are allowed }
  166. constructor init;
  167. constructor init_no_double;
  168. procedure insert(const s : string);
  169. procedure insert_with_tokeninfo(const s : string;const file_info : tfileposinfo);
  170. { gets a string }
  171. function get : string;
  172. function get_with_tokeninfo(var file_info : tfileposinfo) : string;
  173. { true if string is in the container }
  174. function find(const s:string):boolean;
  175. end;
  176. { namedindexobject for use with dictionary and indexarray }
  177. Pnamedindexobject=^Tnamedindexobject;
  178. Tnamedindexobject=object
  179. indexnr : longint;
  180. _name : Pstring;
  181. next,
  182. left,right : Pnamedindexobject;
  183. speedvalue : longint;
  184. constructor init;
  185. constructor initname(const n:string);
  186. destructor done;virtual;
  187. procedure setname(const n:string);virtual;
  188. function name:string;virtual;
  189. end;
  190. Pdictionaryhasharray=^Tdictionaryhasharray;
  191. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of Pnamedindexobject;
  192. Tnamedindexcallback = procedure(p:Pnamedindexobject);
  193. Pdictionary=^Tdictionary;
  194. Tdictionary=object
  195. noclear : boolean;
  196. replace_existing : boolean;
  197. constructor init;
  198. destructor done;virtual;
  199. procedure usehash;
  200. procedure clear;
  201. function delete(const s:string):Pnamedindexobject;
  202. function empty:boolean;
  203. procedure foreach(proc2call:Tnamedindexcallback);
  204. function insert(obj:Pnamedindexobject):Pnamedindexobject;
  205. function rename(const olds,news : string):Pnamedindexobject;
  206. function search(const s:string):Pnamedindexobject;
  207. function speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  208. private
  209. root : Pnamedindexobject;
  210. hasharray : Pdictionaryhasharray;
  211. procedure cleartree(obj:Pnamedindexobject);
  212. function insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  213. procedure inserttree(currtree,currroot:Pnamedindexobject);
  214. end;
  215. pdynamicarray = ^tdynamicarray;
  216. tdynamicarray = object
  217. posn,
  218. count,
  219. limit,
  220. elemlen,
  221. growcount : longint;
  222. data : pchar;
  223. constructor init(Aelemlen,Agrow:longint);
  224. destructor done;
  225. function size:longint;
  226. function usedsize:longint;
  227. procedure grow;
  228. procedure align(i:longint);
  229. procedure seek(i:longint);
  230. procedure write(var d;len:longint);
  231. procedure read(var d;len:longint);
  232. procedure writepos(pos:longint;var d;len:longint);
  233. procedure readpos(pos:longint;var d;len:longint);
  234. end;
  235. tindexobjectarray=array[1..16000] of Pnamedindexobject;
  236. Pnamedindexobjectarray=^tindexobjectarray;
  237. pindexarray=^tindexarray;
  238. tindexarray=object
  239. first : Pnamedindexobject;
  240. count : longint;
  241. constructor init(Agrowsize:longint);
  242. destructor done;
  243. procedure clear;
  244. procedure foreach(proc2call : Tnamedindexcallback);
  245. procedure deleteindex(p:Pnamedindexobject);
  246. procedure delete(p:Pnamedindexobject);
  247. procedure insert(p:Pnamedindexobject);
  248. function search(nr:longint):Pnamedindexobject;
  249. private
  250. growsize,
  251. size : longint;
  252. data : Pnamedindexobjectarray;
  253. procedure grow(gsize:longint);
  254. end;
  255. {$ifdef BUFFEREDFILE}
  256. { this is implemented to allow buffered binary I/O }
  257. pbufferedfile = ^tbufferedfile;
  258. tbufferedfile = object
  259. f : file;
  260. buf : pchar;
  261. bufsize,buflast,bufpos : longint;
  262. { 0 closed, 1 input, 2 output }
  263. iomode : byte;
  264. { true, if the compile should change the endian of the output }
  265. change_endian : boolean;
  266. { calcules a crc for the file, }
  267. { but it's assumed, that there no seek while do_crc is true }
  268. do_crc : boolean;
  269. crc : longint;
  270. { temporary closing feature }
  271. tempclosed : boolean;
  272. tempmode : byte;
  273. temppos : longint;
  274. { inits a buffer with the size bufsize which is assigned to }
  275. { the file filename }
  276. constructor init(const filename : string;_bufsize : longint);
  277. { closes the file, if needed, and releases the memory }
  278. destructor done;virtual;
  279. { opens the file for input, other accesses are rejected }
  280. function reset:boolean;
  281. { opens the file for output, other accesses are rejected }
  282. procedure rewrite;
  283. { reads or writes the buffer from or to disk }
  284. procedure flush;
  285. { writes a string to the file }
  286. { the string is written without a length byte }
  287. procedure write_string(const s : string);
  288. { writes a zero terminated string }
  289. procedure write_pchar(p : pchar);
  290. { write specific data types, takes care of }
  291. { byte order }
  292. procedure write_byte(b : byte);
  293. procedure write_word(w : word);
  294. procedure write_long(l : longint);
  295. procedure write_double(d : double);
  296. { writes any data }
  297. procedure write_data(var data;count : longint);
  298. { reads any data }
  299. procedure read_data(var data;bytes : longint;var count : longint);
  300. { closes the file and releases the buffer }
  301. procedure close;
  302. { temporary closing }
  303. procedure tempclose;
  304. procedure tempreopen;
  305. { goto the given position }
  306. procedure seek(l : longint);
  307. { installes an user defined buffer }
  308. { and releases the old one, but be }
  309. { careful, if the old buffer contains }
  310. { data, this data is lost }
  311. procedure setbuf(p : pchar;s : longint);
  312. { reads the file time stamp of the file, }
  313. { the file must be opened }
  314. function getftime : longint;
  315. { returns filesize }
  316. function getsize : longint;
  317. { returns the path }
  318. function getpath : string;
  319. { resets the crc }
  320. procedure clear_crc;
  321. { returns the crc }
  322. function getcrc : longint;
  323. end;
  324. {$endif BUFFEREDFILE}
  325. {$ifdef fixLeaksOnError}
  326. PStackItem = ^TStackItem;
  327. TStackItem = record
  328. next: PStackItem;
  329. data: pointer;
  330. end;
  331. PStack = ^TStack;
  332. TStack = object
  333. constructor init;
  334. destructor done;
  335. procedure push(p: pointer);
  336. function pop: pointer;
  337. function top: pointer;
  338. function isEmpty: boolean;
  339. private
  340. head: PStackItem;
  341. end;
  342. {$endif fixLeaksOnError}
  343. function getspeedvalue(const s : string) : longint;
  344. { releases the string p and assignes nil to p }
  345. { if p=nil then freemem isn't called }
  346. procedure stringdispose(var p : pstring);
  347. { idem for ansistrings }
  348. procedure ansistringdispose(var p : pchar;length : longint);
  349. { allocates mem for a copy of s, copies s to this mem and returns }
  350. { a pointer to this mem }
  351. function stringdup(const s : string) : pstring;
  352. { allocates memory for s and copies s as zero terminated string
  353. to that mem and returns a pointer to that mem }
  354. function strpnew(const s : string) : pchar;
  355. procedure strdispose(var p : pchar);
  356. { makes a char lowercase, with spanish, french and german char set }
  357. function lowercase(c : char) : char;
  358. { makes zero terminated string to a pascal string }
  359. { the data in p is modified and p is returned }
  360. function pchar2pstring(p : pchar) : pstring;
  361. { ambivalent to pchar2pstring }
  362. function pstring2pchar(p : pstring) : pchar;
  363. implementation
  364. uses
  365. comphook;
  366. {*****************************************************************************
  367. Memory debug
  368. *****************************************************************************}
  369. constructor tmemdebug.init(const s:string);
  370. begin
  371. infostr:=s;
  372. {$ifdef Delphi}
  373. startmem:=0;
  374. {$else}
  375. startmem:=memavail;
  376. {$endif Delphi}
  377. end;
  378. procedure tmemdebug.show;
  379. var
  380. l : longint;
  381. begin
  382. {$ifndef Delphi}
  383. write('memory [',infostr,'] ');
  384. l:=memavail;
  385. if l>startmem then
  386. writeln(l-startmem,' released')
  387. else
  388. writeln(startmem-l,' allocated');
  389. {$endif Delphi}
  390. end;
  391. destructor tmemdebug.done;
  392. begin
  393. show;
  394. end;
  395. {*****************************************************************************
  396. Stack
  397. *****************************************************************************}
  398. {$ifdef fixLeaksOnError}
  399. constructor TStack.init;
  400. begin
  401. head := nil;
  402. end;
  403. procedure TStack.push(p: pointer);
  404. var s: PStackItem;
  405. begin
  406. new(s);
  407. s^.data := p;
  408. s^.next := head;
  409. head := s;
  410. end;
  411. function TStack.pop: pointer;
  412. var s: PStackItem;
  413. begin
  414. pop := top;
  415. if assigned(head) then
  416. begin
  417. s := head^.next;
  418. dispose(head);
  419. head := s;
  420. end
  421. end;
  422. function TStack.top: pointer;
  423. begin
  424. if not isEmpty then
  425. top := head^.data
  426. else top := NIL;
  427. end;
  428. function TStack.isEmpty: boolean;
  429. begin
  430. isEmpty := head = nil;
  431. end;
  432. destructor TStack.done;
  433. var temp: PStackItem;
  434. begin
  435. while head <> nil do
  436. begin
  437. temp := head^.next;
  438. dispose(head);
  439. head := temp;
  440. end;
  441. end;
  442. {$endif fixLeaksOnError}
  443. {$ifndef OLDSPEEDVALUE}
  444. {*****************************************************************************
  445. Crc 32
  446. *****************************************************************************}
  447. var
  448. Crc32Tbl : array[0..255] of longint;
  449. procedure MakeCRC32Tbl;
  450. var
  451. crc : longint;
  452. i,n : byte;
  453. begin
  454. for i:=0 to 255 do
  455. begin
  456. crc:=i;
  457. for n:=1 to 8 do
  458. if odd(crc) then
  459. crc:=(crc shr 1) xor longint($edb88320)
  460. else
  461. crc:=crc shr 1;
  462. Crc32Tbl[i]:=crc;
  463. end;
  464. end;
  465. {$ifopt R+}
  466. {$define Range_check_on}
  467. {$endif opt R+}
  468. {$R- needed here }
  469. {CRC 32}
  470. Function GetSpeedValue(Const s:String):longint;
  471. var
  472. i,InitCrc : longint;
  473. begin
  474. if Crc32Tbl[1]=0 then
  475. MakeCrc32Tbl;
  476. InitCrc:=$ffffffff;
  477. for i:=1 to Length(s) do
  478. InitCrc:=Crc32Tbl[byte(InitCrc) xor ord(s[i])] xor (InitCrc shr 8);
  479. GetSpeedValue:=InitCrc;
  480. end;
  481. {$ifdef Range_check_on}
  482. {$R+}
  483. {$undef Range_check_on}
  484. {$endif Range_check_on}
  485. {$else}
  486. {$ifndef TP}
  487. function getspeedvalue(const s : string) : longint;
  488. var
  489. p1,p2:^byte;
  490. i : longint;
  491. begin
  492. p1:=@s;
  493. longint(p2):=longint(p1)+p1^+1;
  494. inc(longint(p1));
  495. i:=0;
  496. while p1<>p2 do
  497. begin
  498. i:=i + ord(p1^);
  499. inc(longint(p1));
  500. end;
  501. getspeedvalue:=i;
  502. end;
  503. {$else}
  504. function getspeedvalue(const s : string) : longint;
  505. type
  506. ptrrec=record
  507. ofs,seg:word;
  508. end;
  509. var
  510. l,w : longint;
  511. p1,p2 : ^byte;
  512. begin
  513. p1:=@s;
  514. ptrrec(p2).seg:=ptrrec(p1).seg;
  515. ptrrec(p2).ofs:=ptrrec(p1).ofs+p1^+1;
  516. inc(p1);
  517. l:=0;
  518. while p1<>p2 do
  519. begin
  520. l:=l + ord(p1^);
  521. inc(p1);
  522. end;
  523. getspeedvalue:=l;
  524. end;
  525. {$endif}
  526. {$endif OLDSPEEDVALUE}
  527. function pchar2pstring(p : pchar) : pstring;
  528. var
  529. w,i : longint;
  530. begin
  531. w:=strlen(p);
  532. for i:=w-1 downto 0 do
  533. p[i+1]:=p[i];
  534. p[0]:=chr(w);
  535. pchar2pstring:=pstring(p);
  536. end;
  537. function pstring2pchar(p : pstring) : pchar;
  538. var
  539. w,i : longint;
  540. begin
  541. w:=length(p^);
  542. for i:=1 to w do
  543. p^[i-1]:=p^[i];
  544. p^[w]:=#0;
  545. pstring2pchar:=pchar(p);
  546. end;
  547. function lowercase(c : char) : char;
  548. begin
  549. case c of
  550. #65..#90 : c := chr(ord (c) + 32);
  551. #154 : c:=#129; { german }
  552. #142 : c:=#132; { german }
  553. #153 : c:=#148; { german }
  554. #144 : c:=#130; { french }
  555. #128 : c:=#135; { french }
  556. #143 : c:=#134; { swedish/norge (?) }
  557. #165 : c:=#164; { spanish }
  558. #228 : c:=#229; { greek }
  559. #226 : c:=#231; { greek }
  560. #232 : c:=#227; { greek }
  561. end;
  562. lowercase := c;
  563. end;
  564. function strpnew(const s : string) : pchar;
  565. var
  566. p : pchar;
  567. begin
  568. getmem(p,length(s)+1);
  569. strpcopy(p,s);
  570. strpnew:=p;
  571. end;
  572. procedure strdispose(var p : pchar);
  573. begin
  574. if assigned(p) then
  575. begin
  576. freemem(p,strlen(p)+1);
  577. p:=nil;
  578. end;
  579. end;
  580. procedure stringdispose(var p : pstring);
  581. begin
  582. if assigned(p) then
  583. freemem(p,length(p^)+1);
  584. p:=nil;
  585. end;
  586. procedure ansistringdispose(var p : pchar;length : longint);
  587. begin
  588. if assigned(p) then
  589. freemem(p,length+1);
  590. p:=nil;
  591. end;
  592. function stringdup(const s : string) : pstring;
  593. var
  594. p : pstring;
  595. begin
  596. getmem(p,length(s)+1);
  597. p^:=s;
  598. stringdup:=p;
  599. end;
  600. {****************************************************************************
  601. TStringQueue
  602. ****************************************************************************}
  603. constructor TStringQueue.Init;
  604. begin
  605. first:=nil;
  606. last:=nil;
  607. end;
  608. function TStringQueue.Empty:boolean;
  609. begin
  610. Empty:=(first=nil);
  611. end;
  612. function TStringQueue.Get:string;
  613. var
  614. newnode : pstringqueueitem;
  615. begin
  616. if first=nil then
  617. begin
  618. Get:='';
  619. exit;
  620. end;
  621. Get:=first^.data^;
  622. stringdispose(first^.data);
  623. newnode:=first;
  624. first:=first^.next;
  625. dispose(newnode);
  626. end;
  627. function TStringQueue.Find(const s:string):PStringqueueItem;
  628. var
  629. p : PStringqueueItem;
  630. begin
  631. p:=first;
  632. while assigned(p) do
  633. begin
  634. if p^.data^=s then
  635. break;
  636. p:=p^.next;
  637. end;
  638. Find:=p;
  639. end;
  640. function TStringQueue.Delete(const s:string):boolean;
  641. var
  642. prev,p : PStringqueueItem;
  643. begin
  644. Delete:=false;
  645. prev:=nil;
  646. p:=first;
  647. while assigned(p) do
  648. begin
  649. if p^.data^=s then
  650. begin
  651. if p=last then
  652. last:=prev;
  653. if assigned(prev) then
  654. prev^.next:=p^.next
  655. else
  656. first:=p^.next;
  657. dispose(p);
  658. Delete:=true;
  659. exit;
  660. end;
  661. prev:=p;
  662. p:=p^.next;
  663. end;
  664. end;
  665. procedure TStringQueue.Insert(const s:string);
  666. var
  667. newnode : pstringqueueitem;
  668. begin
  669. new(newnode);
  670. newnode^.next:=first;
  671. newnode^.data:=stringdup(s);
  672. first:=newnode;
  673. if last=nil then
  674. last:=newnode;
  675. end;
  676. procedure TStringQueue.Concat(const s:string);
  677. var
  678. newnode : pstringqueueitem;
  679. begin
  680. new(newnode);
  681. newnode^.next:=nil;
  682. newnode^.data:=stringdup(s);
  683. if first=nil then
  684. first:=newnode
  685. else
  686. last^.next:=newnode;
  687. last:=newnode;
  688. end;
  689. procedure TStringQueue.Clear;
  690. var
  691. newnode : pstringqueueitem;
  692. begin
  693. while (first<>nil) do
  694. begin
  695. newnode:=first;
  696. stringdispose(first^.data);
  697. first:=first^.next;
  698. dispose(newnode);
  699. end;
  700. last:=nil;
  701. end;
  702. destructor TStringQueue.Done;
  703. begin
  704. Clear;
  705. end;
  706. {****************************************************************************
  707. TContainerItem
  708. ****************************************************************************}
  709. constructor TContainerItem.Init;
  710. begin
  711. end;
  712. destructor TContainerItem.Done;
  713. begin
  714. end;
  715. {****************************************************************************
  716. TStringContainerItem
  717. ****************************************************************************}
  718. constructor TStringContainerItem.Init(const s:string);
  719. begin
  720. inherited Init;
  721. data:=stringdup(s);
  722. file_info.fileindex:=0;
  723. file_info.line:=0;
  724. file_info.column:=0;
  725. end;
  726. constructor TStringContainerItem.Init_TokenInfo(const s:string;const pos:tfileposinfo);
  727. begin
  728. inherited Init;
  729. data:=stringdup(s);
  730. file_info:=pos;
  731. end;
  732. destructor TStringContainerItem.Done;
  733. begin
  734. stringdispose(data);
  735. end;
  736. {****************************************************************************
  737. TCONTAINER
  738. ****************************************************************************}
  739. constructor tcontainer.init;
  740. begin
  741. root:=nil;
  742. last:=nil;
  743. end;
  744. destructor tcontainer.done;
  745. begin
  746. clear;
  747. end;
  748. function tcontainer.empty:boolean;
  749. begin
  750. empty:=(root=nil);
  751. end;
  752. procedure tcontainer.insert(item:pcontaineritem);
  753. begin
  754. item^.next:=nil;
  755. if root=nil then
  756. root:=item
  757. else
  758. last^.next:=item;
  759. last:=item;
  760. end;
  761. procedure tcontainer.clear;
  762. var
  763. newnode : pcontaineritem;
  764. begin
  765. newnode:=root;
  766. while assigned(newnode) do
  767. begin
  768. root:=newnode^.next;
  769. dispose(newnode,done);
  770. newnode:=root;
  771. end;
  772. last:=nil;
  773. root:=nil;
  774. end;
  775. function tcontainer.get:pcontaineritem;
  776. begin
  777. if root=nil then
  778. get:=nil
  779. else
  780. begin
  781. get:=root;
  782. root:=root^.next;
  783. end;
  784. end;
  785. {****************************************************************************
  786. TSTRINGCONTAINER
  787. ****************************************************************************}
  788. constructor tstringcontainer.init;
  789. begin
  790. inherited init;
  791. doubles:=true;
  792. end;
  793. constructor tstringcontainer.init_no_double;
  794. begin
  795. inherited init;
  796. doubles:=false;
  797. end;
  798. procedure tstringcontainer.insert(const s : string);
  799. var
  800. newnode : pstringcontaineritem;
  801. begin
  802. if (s='') or
  803. ((not doubles) and find(s)) then
  804. exit;
  805. new(newnode,init(s));
  806. inherited insert(newnode);
  807. end;
  808. procedure tstringcontainer.insert_with_tokeninfo(const s : string; const file_info : tfileposinfo);
  809. var
  810. newnode : pstringcontaineritem;
  811. begin
  812. if (not doubles) and find(s) then
  813. exit;
  814. new(newnode,init_tokeninfo(s,file_info));
  815. inherited insert(newnode);
  816. end;
  817. function tstringcontainer.get : string;
  818. var
  819. p : pstringcontaineritem;
  820. begin
  821. p:=pstringcontaineritem(inherited get);
  822. if p=nil then
  823. get:=''
  824. else
  825. begin
  826. get:=p^.data^;
  827. dispose(p,done);
  828. end;
  829. end;
  830. function tstringcontainer.get_with_tokeninfo(var file_info : tfileposinfo) : string;
  831. var
  832. p : pstringcontaineritem;
  833. begin
  834. p:=pstringcontaineritem(inherited get);
  835. if p=nil then
  836. begin
  837. get_with_tokeninfo:='';
  838. file_info.fileindex:=0;
  839. file_info.line:=0;
  840. file_info.column:=0;
  841. end
  842. else
  843. begin
  844. get_with_tokeninfo:=p^.data^;
  845. file_info:=p^.file_info;
  846. dispose(p,done);
  847. end;
  848. end;
  849. function tstringcontainer.find(const s:string):boolean;
  850. var
  851. newnode : pstringcontaineritem;
  852. begin
  853. find:=false;
  854. newnode:=pstringcontaineritem(root);
  855. while assigned(newnode) do
  856. begin
  857. if newnode^.data^=s then
  858. begin
  859. find:=true;
  860. exit;
  861. end;
  862. newnode:=pstringcontaineritem(newnode^.next);
  863. end;
  864. end;
  865. {****************************************************************************
  866. TLINKEDLIST_ITEM
  867. ****************************************************************************}
  868. constructor tlinkedlist_item.init;
  869. begin
  870. previous:=nil;
  871. next:=nil;
  872. end;
  873. destructor tlinkedlist_item.done;
  874. begin
  875. end;
  876. function tlinkedlist_item.getcopy:plinkedlist_item;
  877. var
  878. l : longint;
  879. p : plinkedlist_item;
  880. begin
  881. l:=sizeof(self);
  882. getmem(p,l);
  883. move(self,p^,l);
  884. getcopy:=p;
  885. end;
  886. {****************************************************************************
  887. TSTRING_ITEM
  888. ****************************************************************************}
  889. constructor tstring_item.init(const s : string);
  890. begin
  891. str:=stringdup(s);
  892. end;
  893. destructor tstring_item.done;
  894. begin
  895. stringdispose(str);
  896. inherited done;
  897. end;
  898. {****************************************************************************
  899. TLINKEDLIST
  900. ****************************************************************************}
  901. constructor tlinkedlist.init;
  902. begin
  903. first:=nil;
  904. last:=nil;
  905. end;
  906. destructor tlinkedlist.done;
  907. begin
  908. clear;
  909. end;
  910. destructor tlinkedlist.done_noclear;
  911. begin
  912. end;
  913. procedure tlinkedlist.clear;
  914. var
  915. newnode : plinkedlist_item;
  916. begin
  917. newnode:=first;
  918. while assigned(newnode) do
  919. begin
  920. first:=newnode^.next;
  921. dispose(newnode,done);
  922. newnode:=first;
  923. end;
  924. end;
  925. procedure tlinkedlist.insertlist(p : plinkedlist);
  926. begin
  927. { empty list ? }
  928. if not(assigned(p^.first)) then
  929. exit;
  930. p^.last^.next:=first;
  931. { we have a double linked list }
  932. if assigned(first) then
  933. first^.previous:=p^.last;
  934. first:=p^.first;
  935. if not(assigned(last)) then
  936. last:=p^.last;
  937. { p becomes empty }
  938. p^.first:=nil;
  939. p^.last:=nil;
  940. end;
  941. procedure tlinkedlist.concat(p : plinkedlist_item);
  942. begin
  943. if not(assigned(first)) then
  944. begin
  945. first:=p;
  946. p^.previous:=nil;
  947. p^.next:=nil;
  948. end
  949. else
  950. begin
  951. last^.next:=p;
  952. p^.previous:=last;
  953. p^.next:=nil;
  954. end;
  955. last:=p;
  956. end;
  957. procedure tlinkedlist.insert(p : plinkedlist_item);
  958. begin
  959. if not(assigned(first)) then
  960. begin
  961. last:=p;
  962. p^.previous:=nil;
  963. p^.next:=nil;
  964. end
  965. else
  966. begin
  967. first^.previous:=p;
  968. p^.previous:=nil;
  969. p^.next:=first;
  970. end;
  971. first:=p;
  972. end;
  973. procedure tlinkedlist.remove(p : plinkedlist_item);
  974. begin
  975. if not(assigned(p)) then
  976. exit;
  977. if (first=p) and (last=p) then
  978. begin
  979. first:=nil;
  980. last:=nil;
  981. end
  982. else if first=p then
  983. begin
  984. first:=p^.next;
  985. if assigned(first) then
  986. first^.previous:=nil;
  987. end
  988. else if last=p then
  989. begin
  990. last:=last^.previous;
  991. if assigned(last) then
  992. last^.next:=nil;
  993. end
  994. else
  995. begin
  996. p^.previous^.next:=p^.next;
  997. p^.next^.previous:=p^.previous;
  998. end;
  999. p^.next:=nil;
  1000. p^.previous:=nil;
  1001. end;
  1002. procedure tlinkedlist.concatlist(p : plinkedlist);
  1003. begin
  1004. if not(assigned(p^.first)) then
  1005. exit;
  1006. if not(assigned(first)) then
  1007. first:=p^.first
  1008. else
  1009. begin
  1010. last^.next:=p^.first;
  1011. p^.first^.previous:=last;
  1012. end;
  1013. last:=p^.last;
  1014. { make p empty }
  1015. p^.last:=nil;
  1016. p^.first:=nil;
  1017. end;
  1018. procedure tlinkedlist.concatlistcopy(p : plinkedlist);
  1019. var
  1020. newnode,newnode2 : plinkedlist_item;
  1021. begin
  1022. newnode:=p^.first;
  1023. while assigned(newnode) do
  1024. begin
  1025. newnode2:=newnode^.getcopy;
  1026. if assigned(newnode2) then
  1027. begin
  1028. if not(assigned(first)) then
  1029. begin
  1030. first:=newnode2;
  1031. newnode2^.previous:=nil;
  1032. newnode2^.next:=nil;
  1033. end
  1034. else
  1035. begin
  1036. last^.next:=newnode2;
  1037. newnode2^.previous:=last;
  1038. newnode2^.next:=nil;
  1039. end;
  1040. last:=newnode2;
  1041. end;
  1042. newnode:=newnode^.next;
  1043. end;
  1044. end;
  1045. function tlinkedlist.empty:boolean;
  1046. begin
  1047. empty:=(first=nil);
  1048. end;
  1049. function tlinkedlist.count:longint;
  1050. var
  1051. i : longint;
  1052. hp : plinkedlist_item;
  1053. begin
  1054. hp:=first;
  1055. i:=0;
  1056. while assigned(hp) do
  1057. begin
  1058. inc(i);
  1059. hp:=hp^.next;
  1060. end;
  1061. count:=i;
  1062. end;
  1063. {****************************************************************************
  1064. Tnamedindexobject
  1065. ****************************************************************************}
  1066. constructor Tnamedindexobject.init;
  1067. begin
  1068. { index }
  1069. indexnr:=-1;
  1070. next:=nil;
  1071. { dictionary }
  1072. left:=nil;
  1073. right:=nil;
  1074. _name:=nil;
  1075. speedvalue:=-1;
  1076. end;
  1077. constructor Tnamedindexobject.initname(const n:string);
  1078. begin
  1079. { index }
  1080. indexnr:=-1;
  1081. next:=nil;
  1082. { dictionary }
  1083. left:=nil;
  1084. right:=nil;
  1085. speedvalue:=-1;
  1086. _name:=stringdup(n);
  1087. end;
  1088. destructor Tnamedindexobject.done;
  1089. begin
  1090. stringdispose(_name);
  1091. end;
  1092. procedure Tnamedindexobject.setname(const n:string);
  1093. begin
  1094. if speedvalue=-1 then
  1095. begin
  1096. if assigned(_name) then
  1097. stringdispose(_name);
  1098. _name:=stringdup(n);
  1099. end;
  1100. end;
  1101. function Tnamedindexobject.name:string;
  1102. begin
  1103. if assigned(_name) then
  1104. name:=_name^
  1105. else
  1106. name:='';
  1107. end;
  1108. {****************************************************************************
  1109. TDICTIONARY
  1110. ****************************************************************************}
  1111. constructor Tdictionary.init;
  1112. begin
  1113. root:=nil;
  1114. hasharray:=nil;
  1115. noclear:=false;
  1116. replace_existing:=false;
  1117. end;
  1118. procedure Tdictionary.usehash;
  1119. begin
  1120. if not(assigned(root)) and
  1121. not(assigned(hasharray)) then
  1122. begin
  1123. new(hasharray);
  1124. fillchar(hasharray^,sizeof(hasharray^),0);
  1125. end;
  1126. end;
  1127. destructor Tdictionary.done;
  1128. begin
  1129. if not noclear then
  1130. clear;
  1131. if assigned(hasharray) then
  1132. dispose(hasharray);
  1133. end;
  1134. procedure Tdictionary.cleartree(obj:Pnamedindexobject);
  1135. begin
  1136. if assigned(obj^.left) then
  1137. cleartree(obj^.left);
  1138. if assigned(obj^.right) then
  1139. cleartree(obj^.right);
  1140. dispose(obj,done);
  1141. obj:=nil;
  1142. end;
  1143. procedure Tdictionary.clear;
  1144. var
  1145. w : longint;
  1146. begin
  1147. if assigned(root) then
  1148. cleartree(root);
  1149. if assigned(hasharray) then
  1150. for w:=-hasharraysize to hasharraysize do
  1151. if assigned(hasharray^[w]) then
  1152. cleartree(hasharray^[w]);
  1153. end;
  1154. function Tdictionary.delete(const s:string):Pnamedindexobject;
  1155. var p,speedvalue:longint;
  1156. n:Pnamedindexobject;
  1157. procedure insert_right_bottom(var root,Atree:Pnamedindexobject);
  1158. begin
  1159. while root^.right<>nil do
  1160. root:=root^.right;
  1161. root^.right:=Atree;
  1162. end;
  1163. function delete_from_tree(root:Pnamedindexobject):Pnamedindexobject;
  1164. type leftright=(left,right);
  1165. var lr:leftright;
  1166. oldroot:Pnamedindexobject;
  1167. begin
  1168. oldroot:=nil;
  1169. while (root<>nil) and (root^.speedvalue<>speedvalue) do
  1170. begin
  1171. oldroot:=root;
  1172. if speedvalue<root^.speedvalue then
  1173. begin
  1174. root:=root^.right;
  1175. lr:=right;
  1176. end
  1177. else
  1178. begin
  1179. root:=root^.left;
  1180. lr:=left;
  1181. end;
  1182. end;
  1183. while (root<>nil) and (root^._name^<>s) do
  1184. begin
  1185. oldroot:=root;
  1186. if s<root^._name^ then
  1187. begin
  1188. root:=root^.right;
  1189. lr:=right;
  1190. end
  1191. else
  1192. begin
  1193. root:=root^.left;
  1194. lr:=left;
  1195. end;
  1196. end;
  1197. if (oldroot=nil) or (root=nil) then
  1198. do_internalerror(218); {Internalerror is not available...}
  1199. if root^.left<>nil then
  1200. begin
  1201. {Now the node pointing to root must point to the left
  1202. subtree of root. The right subtree of root must be
  1203. connected to the right bottom of the left subtree.}
  1204. if lr=left then
  1205. oldroot^.left:=root^.left
  1206. else
  1207. oldroot^.right:=root^.left;
  1208. if root^.right<>nil then
  1209. insert_right_bottom(root^.left,root^.right);
  1210. end
  1211. else
  1212. {There is no left subtree. So we can just replace the node to
  1213. delete with the right subtree.}
  1214. if lr=left then
  1215. oldroot^.left:=root^.right
  1216. else
  1217. oldroot^.right:=root^.right;
  1218. delete_from_tree:=root;
  1219. end;
  1220. begin
  1221. speedvalue:=getspeedvalue(s);
  1222. n:=root;
  1223. if assigned(hasharray) then
  1224. begin
  1225. {First, check if the node to delete directly located under
  1226. the hasharray.}
  1227. p:=speedvalue mod hasharraysize;
  1228. n:=hasharray^[p];
  1229. if (n<>nil) and (n^.speedvalue=speedvalue) and
  1230. (n^._name^=s) then
  1231. begin
  1232. {The node to delete is directly located under the
  1233. hasharray. Make the hasharray point to the left
  1234. subtree of the node and place the right subtree on
  1235. the right-bottom of the left subtree.}
  1236. if n^.left<>nil then
  1237. begin
  1238. hasharray^[p]:=n^.left;
  1239. if n^.right<>nil then
  1240. insert_right_bottom(n^.left,n^.right);
  1241. end
  1242. else
  1243. hasharray^[p]:=n^.right;
  1244. delete:=n;
  1245. exit;
  1246. end;
  1247. end
  1248. else
  1249. begin
  1250. {First check if the node to delete is the root.}
  1251. if (root<>nil) and (n^.speedvalue=speedvalue)
  1252. and (n^._name^=s) then
  1253. begin
  1254. if n^.left<>nil then
  1255. begin
  1256. root:=n^.left;
  1257. if n^.right<>nil then
  1258. insert_right_bottom(n^.left,n^.right);
  1259. end
  1260. else
  1261. root:=n^.right;
  1262. delete:=n;
  1263. exit;
  1264. end;
  1265. end;
  1266. delete:=delete_from_tree(n);
  1267. end;
  1268. function Tdictionary.empty:boolean;
  1269. var
  1270. w : longint;
  1271. begin
  1272. if assigned(hasharray) then
  1273. begin
  1274. empty:=false;
  1275. for w:=-hasharraysize to hasharraysize do
  1276. if assigned(hasharray^[w]) then
  1277. exit;
  1278. empty:=true;
  1279. end
  1280. else
  1281. empty:=(root=nil);
  1282. end;
  1283. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  1284. procedure a(p:Pnamedindexobject);
  1285. begin
  1286. proc2call(p);
  1287. if assigned(p^.left) then
  1288. a(p^.left);
  1289. if assigned(p^.right) then
  1290. a(p^.right);
  1291. end;
  1292. var
  1293. i : longint;
  1294. begin
  1295. if assigned(hasharray) then
  1296. begin
  1297. for i:=-hasharraysize to hasharraysize do
  1298. if assigned(hasharray^[i]) then
  1299. a(hasharray^[i]);
  1300. end
  1301. else
  1302. if assigned(root) then
  1303. a(root);
  1304. end;
  1305. function Tdictionary.insert(obj:Pnamedindexobject):Pnamedindexobject;
  1306. begin
  1307. obj^.speedvalue:=getspeedvalue(obj^._name^);
  1308. if assigned(hasharray) then
  1309. insert:=insertnode(obj,hasharray^[obj^.speedvalue mod hasharraysize])
  1310. else
  1311. insert:=insertnode(obj,root);
  1312. end;
  1313. function tdictionary.insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  1314. begin
  1315. if currnode=nil then
  1316. begin
  1317. currnode:=newnode;
  1318. insertnode:=newnode;
  1319. end
  1320. { first check speedvalue, to allow a fast insert }
  1321. else
  1322. if currnode^.speedvalue>newnode^.speedvalue then
  1323. insertnode:=insertnode(newnode,currnode^.right)
  1324. else
  1325. if currnode^.speedvalue<newnode^.speedvalue then
  1326. insertnode:=insertnode(newnode,currnode^.left)
  1327. else
  1328. begin
  1329. if currnode^._name^>newnode^._name^ then
  1330. insertnode:=insertnode(newnode,currnode^.right)
  1331. else
  1332. if currnode^._name^<newnode^._name^ then
  1333. insertnode:=insertnode(newnode,currnode^.left)
  1334. else
  1335. begin
  1336. if replace_existing and
  1337. assigned(currnode) then
  1338. begin
  1339. newnode^.left:=currnode^.left;
  1340. newnode^.right:=currnode^.right;
  1341. currnode:=newnode;
  1342. insertnode:=newnode;
  1343. end
  1344. else
  1345. insertnode:=currnode;
  1346. end;
  1347. end;
  1348. end;
  1349. procedure tdictionary.inserttree(currtree,currroot:Pnamedindexobject);
  1350. begin
  1351. if assigned(currtree) then
  1352. begin
  1353. inserttree(currtree^.left,currroot);
  1354. inserttree(currtree^.right,currroot);
  1355. currtree^.right:=nil;
  1356. currtree^.left:=nil;
  1357. insertnode(currtree,currroot);
  1358. end;
  1359. end;
  1360. function tdictionary.rename(const olds,news : string):Pnamedindexobject;
  1361. var
  1362. spdval : longint;
  1363. lasthp,
  1364. hp,hp2,hp3 : Pnamedindexobject;
  1365. begin
  1366. spdval:=getspeedvalue(olds);
  1367. if assigned(hasharray) then
  1368. hp:=hasharray^[spdval mod hasharraysize]
  1369. else
  1370. hp:=root;
  1371. lasthp:=nil;
  1372. while assigned(hp) do
  1373. begin
  1374. if spdval>hp^.speedvalue then
  1375. begin
  1376. lasthp:=hp;
  1377. hp:=hp^.left
  1378. end
  1379. else
  1380. if spdval<hp^.speedvalue then
  1381. begin
  1382. lasthp:=hp;
  1383. hp:=hp^.right
  1384. end
  1385. else
  1386. begin
  1387. if (hp^.name=olds) then
  1388. begin
  1389. { get in hp2 the replacer for the root or hasharr }
  1390. hp2:=hp^.left;
  1391. hp3:=hp^.right;
  1392. if not assigned(hp2) then
  1393. begin
  1394. hp2:=hp^.right;
  1395. hp3:=hp^.left;
  1396. end;
  1397. { remove entry from the tree }
  1398. if assigned(lasthp) then
  1399. begin
  1400. if lasthp^.left=hp then
  1401. lasthp^.left:=hp2
  1402. else
  1403. lasthp^.right:=hp2;
  1404. end
  1405. else
  1406. begin
  1407. if assigned(hasharray) then
  1408. hasharray^[spdval mod hasharraysize]:=hp2
  1409. else
  1410. root:=hp2;
  1411. end;
  1412. { reinsert the hp3 in the tree from hp2 }
  1413. inserttree(hp3,hp2);
  1414. { reset node with new values }
  1415. stringdispose(hp^._name);
  1416. hp^._name:=stringdup(news);
  1417. hp^.speedvalue:=getspeedvalue(news);
  1418. hp^.left:=nil;
  1419. hp^.right:=nil;
  1420. { reinsert }
  1421. if assigned(hasharray) then
  1422. rename:=insertnode(hp,hasharray^[hp^.speedvalue mod hasharraysize])
  1423. else
  1424. rename:=insertnode(hp,root);
  1425. exit;
  1426. end
  1427. else
  1428. if olds>hp^.name then
  1429. begin
  1430. lasthp:=hp;
  1431. hp:=hp^.left
  1432. end
  1433. else
  1434. begin
  1435. lasthp:=hp;
  1436. hp:=hp^.right;
  1437. end;
  1438. end;
  1439. end;
  1440. end;
  1441. function Tdictionary.search(const s:string):Pnamedindexobject;
  1442. begin
  1443. search:=speedsearch(s,getspeedvalue(s));
  1444. end;
  1445. function Tdictionary.speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  1446. var
  1447. newnode:Pnamedindexobject;
  1448. begin
  1449. if assigned(hasharray) then
  1450. newnode:=hasharray^[speedvalue mod hasharraysize]
  1451. else
  1452. newnode:=root;
  1453. while assigned(newnode) do
  1454. begin
  1455. if speedvalue>newnode^.speedvalue then
  1456. newnode:=newnode^.left
  1457. else
  1458. if speedvalue<newnode^.speedvalue then
  1459. newnode:=newnode^.right
  1460. else
  1461. begin
  1462. if (newnode^._name^=s) then
  1463. begin
  1464. speedsearch:=newnode;
  1465. exit;
  1466. end
  1467. else
  1468. if s>newnode^._name^ then
  1469. newnode:=newnode^.left
  1470. else
  1471. newnode:=newnode^.right;
  1472. end;
  1473. end;
  1474. speedsearch:=nil;
  1475. end;
  1476. {****************************************************************************
  1477. tdynamicarray
  1478. ****************************************************************************}
  1479. constructor tdynamicarray.init(Aelemlen,Agrow:longint);
  1480. begin
  1481. posn:=0;
  1482. count:=0;
  1483. limit:=0;
  1484. data:=nil;
  1485. elemlen:=Aelemlen;
  1486. growcount:=Agrow;
  1487. grow;
  1488. end;
  1489. function tdynamicarray.size:longint;
  1490. begin
  1491. size:=limit*elemlen;
  1492. end;
  1493. function tdynamicarray.usedsize:longint;
  1494. begin
  1495. usedsize:=count*elemlen;
  1496. end;
  1497. procedure tdynamicarray.grow;
  1498. var
  1499. osize : longint;
  1500. odata : pchar;
  1501. begin
  1502. osize:=size;
  1503. odata:=data;
  1504. inc(limit,growcount);
  1505. getmem(data,size);
  1506. if assigned(odata) then
  1507. begin
  1508. move(odata^,data^,osize);
  1509. freemem(odata,osize);
  1510. end;
  1511. fillchar(data[osize],growcount*elemlen,0);
  1512. end;
  1513. procedure tdynamicarray.align(i:longint);
  1514. var
  1515. j : longint;
  1516. begin
  1517. j:=(posn*elemlen mod i);
  1518. if j<>0 then
  1519. begin
  1520. j:=i-j;
  1521. while limit<(posn+j) do
  1522. grow;
  1523. inc(posn,j);
  1524. if (posn>count) then
  1525. count:=posn;
  1526. end;
  1527. end;
  1528. procedure tdynamicarray.seek(i:longint);
  1529. begin
  1530. while limit<i do
  1531. grow;
  1532. posn:=i;
  1533. if (posn>count) then
  1534. count:=posn;
  1535. end;
  1536. procedure tdynamicarray.write(var d;len:longint);
  1537. begin
  1538. while limit<(posn+len) do
  1539. grow;
  1540. move(d,data[posn*elemlen],len*elemlen);
  1541. inc(posn,len);
  1542. if (posn>count) then
  1543. count:=posn;
  1544. end;
  1545. procedure tdynamicarray.read(var d;len:longint);
  1546. begin
  1547. move(data[posn*elemlen],d,len*elemlen);
  1548. inc(posn,len);
  1549. if (posn>count) then
  1550. count:=posn;
  1551. end;
  1552. procedure tdynamicarray.writepos(pos:longint;var d;len:longint);
  1553. begin
  1554. while limit<(pos+len) do
  1555. grow;
  1556. move(d,data[pos*elemlen],len*elemlen);
  1557. posn:=pos+len;
  1558. if (posn>count) then
  1559. count:=posn;
  1560. end;
  1561. procedure tdynamicarray.readpos(pos:longint;var d;len:longint);
  1562. begin
  1563. while limit<(pos+len) do
  1564. grow;
  1565. move(data[pos*elemlen],d,len*elemlen);
  1566. posn:=pos+len;
  1567. if (posn>count) then
  1568. count:=posn;
  1569. end;
  1570. destructor tdynamicarray.done;
  1571. begin
  1572. if assigned(data) then
  1573. freemem(data,size);
  1574. end;
  1575. {****************************************************************************
  1576. tindexarray
  1577. ****************************************************************************}
  1578. constructor tindexarray.init(Agrowsize:longint);
  1579. begin
  1580. growsize:=Agrowsize;
  1581. size:=0;
  1582. count:=0;
  1583. data:=nil;
  1584. first:=nil;
  1585. end;
  1586. destructor tindexarray.done;
  1587. begin
  1588. if assigned(data) then
  1589. begin
  1590. clear;
  1591. freemem(data,size*4);
  1592. data:=nil;
  1593. end;
  1594. end;
  1595. function tindexarray.search(nr:longint):Pnamedindexobject;
  1596. begin
  1597. if nr<=count then
  1598. search:=data^[nr]
  1599. else
  1600. search:=nil;
  1601. end;
  1602. procedure tindexarray.clear;
  1603. var
  1604. i : longint;
  1605. begin
  1606. for i:=1 to count do
  1607. if assigned(data^[i]) then
  1608. begin
  1609. dispose(data^[i],done);
  1610. data^[i]:=nil;
  1611. end;
  1612. count:=0;
  1613. first:=nil;
  1614. end;
  1615. procedure tindexarray.foreach(proc2call : Tnamedindexcallback);
  1616. var
  1617. i : longint;
  1618. begin
  1619. for i:=1 to count do
  1620. if assigned(data^[i]) then
  1621. proc2call(data^[i]);
  1622. end;
  1623. procedure tindexarray.grow(gsize:longint);
  1624. var
  1625. osize : longint;
  1626. odata : Pnamedindexobjectarray;
  1627. begin
  1628. osize:=size;
  1629. odata:=data;
  1630. inc(size,gsize);
  1631. getmem(data,size*4);
  1632. if assigned(odata) then
  1633. begin
  1634. move(odata^,data^,osize*4);
  1635. freemem(odata,osize*4);
  1636. end;
  1637. fillchar(data^[osize+1],gsize*4,0);
  1638. end;
  1639. procedure tindexarray.deleteindex(p:Pnamedindexobject);
  1640. var
  1641. i : longint;
  1642. begin
  1643. i:=p^.indexnr;
  1644. { update counter }
  1645. if i=count then
  1646. dec(count);
  1647. { update linked list }
  1648. while (i>0) do
  1649. begin
  1650. dec(i);
  1651. if (i>0) and assigned(data^[i]) then
  1652. begin
  1653. data^[i]^.next:=data^[p^.indexnr]^.next;
  1654. break;
  1655. end;
  1656. end;
  1657. if i=0 then
  1658. first:=p^.next;
  1659. data^[p^.indexnr]:=nil;
  1660. { clear entry }
  1661. p^.indexnr:=-1;
  1662. p^.next:=nil;
  1663. end;
  1664. procedure tindexarray.delete(p:Pnamedindexobject);
  1665. begin
  1666. deleteindex(p);
  1667. dispose(p,done);
  1668. p:=nil;
  1669. end;
  1670. procedure tindexarray.insert(p:Pnamedindexobject);
  1671. var
  1672. i : longint;
  1673. begin
  1674. if p^.indexnr=-1 then
  1675. begin
  1676. inc(count);
  1677. p^.indexnr:=count;
  1678. end;
  1679. if p^.indexnr>count then
  1680. count:=p^.indexnr;
  1681. if count>size then
  1682. grow(((count div growsize)+1)*growsize);
  1683. data^[p^.indexnr]:=p;
  1684. { update linked list backward }
  1685. i:=p^.indexnr;
  1686. while (i>0) do
  1687. begin
  1688. dec(i);
  1689. if (i>0) and assigned(data^[i]) then
  1690. begin
  1691. data^[i]^.next:=p;
  1692. break;
  1693. end;
  1694. end;
  1695. if i=0 then
  1696. first:=p;
  1697. { update linked list forward }
  1698. i:=p^.indexnr;
  1699. while (i<=count) do
  1700. begin
  1701. inc(i);
  1702. if (i<=count) and assigned(data^[i]) then
  1703. begin
  1704. p^.next:=data^[i];
  1705. exit;
  1706. end;
  1707. end;
  1708. if i>count then
  1709. p^.next:=nil;
  1710. end;
  1711. {$ifdef BUFFEREDFILE}
  1712. {****************************************************************************
  1713. TBUFFEREDFILE
  1714. ****************************************************************************}
  1715. Const
  1716. crcseed = $ffffffff;
  1717. crctable : array[0..255] of longint = (
  1718. $00000000,$77073096,$ee0e612c,$990951ba,$076dc419,$706af48f,
  1719. $e963a535,$9e6495a3,$0edb8832,$79dcb8a4,$e0d5e91e,$97d2d988,
  1720. $09b64c2b,$7eb17cbd,$e7b82d07,$90bf1d91,$1db71064,$6ab020f2,
  1721. $f3b97148,$84be41de,$1adad47d,$6ddde4eb,$f4d4b551,$83d385c7,
  1722. $136c9856,$646ba8c0,$fd62f97a,$8a65c9ec,$14015c4f,$63066cd9,
  1723. $fa0f3d63,$8d080df5,$3b6e20c8,$4c69105e,$d56041e4,$a2677172,
  1724. $3c03e4d1,$4b04d447,$d20d85fd,$a50ab56b,$35b5a8fa,$42b2986c,
  1725. $dbbbc9d6,$acbcf940,$32d86ce3,$45df5c75,$dcd60dcf,$abd13d59,
  1726. $26d930ac,$51de003a,$c8d75180,$bfd06116,$21b4f4b5,$56b3c423,
  1727. $cfba9599,$b8bda50f,$2802b89e,$5f058808,$c60cd9b2,$b10be924,
  1728. $2f6f7c87,$58684c11,$c1611dab,$b6662d3d,$76dc4190,$01db7106,
  1729. $98d220bc,$efd5102a,$71b18589,$06b6b51f,$9fbfe4a5,$e8b8d433,
  1730. $7807c9a2,$0f00f934,$9609a88e,$e10e9818,$7f6a0dbb,$086d3d2d,
  1731. $91646c97,$e6635c01,$6b6b51f4,$1c6c6162,$856530d8,$f262004e,
  1732. $6c0695ed,$1b01a57b,$8208f4c1,$f50fc457,$65b0d9c6,$12b7e950,
  1733. $8bbeb8ea,$fcb9887c,$62dd1ddf,$15da2d49,$8cd37cf3,$fbd44c65,
  1734. $4db26158,$3ab551ce,$a3bc0074,$d4bb30e2,$4adfa541,$3dd895d7,
  1735. $a4d1c46d,$d3d6f4fb,$4369e96a,$346ed9fc,$ad678846,$da60b8d0,
  1736. $44042d73,$33031de5,$aa0a4c5f,$dd0d7cc9,$5005713c,$270241aa,
  1737. $be0b1010,$c90c2086,$5768b525,$206f85b3,$b966d409,$ce61e49f,
  1738. $5edef90e,$29d9c998,$b0d09822,$c7d7a8b4,$59b33d17,$2eb40d81,
  1739. $b7bd5c3b,$c0ba6cad,$edb88320,$9abfb3b6,$03b6e20c,$74b1d29a,
  1740. $ead54739,$9dd277af,$04db2615,$73dc1683,$e3630b12,$94643b84,
  1741. $0d6d6a3e,$7a6a5aa8,$e40ecf0b,$9309ff9d,$0a00ae27,$7d079eb1,
  1742. $f00f9344,$8708a3d2,$1e01f268,$6906c2fe,$f762575d,$806567cb,
  1743. $196c3671,$6e6b06e7,$fed41b76,$89d32be0,$10da7a5a,$67dd4acc,
  1744. $f9b9df6f,$8ebeeff9,$17b7be43,$60b08ed5,$d6d6a3e8,$a1d1937e,
  1745. $38d8c2c4,$4fdff252,$d1bb67f1,$a6bc5767,$3fb506dd,$48b2364b,
  1746. $d80d2bda,$af0a1b4c,$36034af6,$41047a60,$df60efc3,$a867df55,
  1747. $316e8eef,$4669be79,$cb61b38c,$bc66831a,$256fd2a0,$5268e236,
  1748. $cc0c7795,$bb0b4703,$220216b9,$5505262f,$c5ba3bbe,$b2bd0b28,
  1749. $2bb45a92,$5cb36a04,$c2d7ffa7,$b5d0cf31,$2cd99e8b,$5bdeae1d,
  1750. $9b64c2b0,$ec63f226,$756aa39c,$026d930a,$9c0906a9,$eb0e363f,
  1751. $72076785,$05005713,$95bf4a82,$e2b87a14,$7bb12bae,$0cb61b38,
  1752. $92d28e9b,$e5d5be0d,$7cdcefb7,$0bdbdf21,$86d3d2d4,$f1d4e242,
  1753. $68ddb3f8,$1fda836e,$81be16cd,$f6b9265b,$6fb077e1,$18b74777,
  1754. $88085ae6,$ff0f6a70,$66063bca,$11010b5c,$8f659eff,$f862ae69,
  1755. $616bffd3,$166ccf45,$a00ae278,$d70dd2ee,$4e048354,$3903b3c2,
  1756. $a7672661,$d06016f7,$4969474d,$3e6e77db,$aed16a4a,$d9d65adc,
  1757. $40df0b66,$37d83bf0,$a9bcae53,$debb9ec5,$47b2cf7f,$30b5ffe9,
  1758. $bdbdf21c,$cabac28a,$53b39330,$24b4a3a6,$bad03605,$cdd70693,
  1759. $54de5729,$23d967bf,$b3667a2e,$c4614ab8,$5d681b02,$2a6f2b94,
  1760. $b40bbe37,$c30c8ea1,$5a05df1b,$2d02ef8d);
  1761. constructor tbufferedfile.init(const filename : string;_bufsize : longint);
  1762. begin
  1763. assign(f,filename);
  1764. bufsize:=_bufsize;
  1765. bufpos:=0;
  1766. buflast:=0;
  1767. do_crc:=false;
  1768. iomode:=0;
  1769. tempclosed:=false;
  1770. change_endian:=false;
  1771. clear_crc;
  1772. end;
  1773. destructor tbufferedfile.done;
  1774. begin
  1775. close;
  1776. end;
  1777. procedure tbufferedfile.clear_crc;
  1778. begin
  1779. crc:=crcseed;
  1780. end;
  1781. procedure tbufferedfile.setbuf(p : pchar;s : longint);
  1782. begin
  1783. flush;
  1784. freemem(buf,bufsize);
  1785. bufsize:=s;
  1786. buf:=p;
  1787. end;
  1788. function tbufferedfile.reset:boolean;
  1789. var
  1790. ofm : byte;
  1791. begin
  1792. ofm:=filemode;
  1793. iomode:=1;
  1794. getmem(buf,bufsize);
  1795. filemode:=0;
  1796. {$I-}
  1797. system.reset(f,1);
  1798. {$I+}
  1799. reset:=(ioresult=0);
  1800. filemode:=ofm;
  1801. end;
  1802. procedure tbufferedfile.rewrite;
  1803. begin
  1804. iomode:=2;
  1805. getmem(buf,bufsize);
  1806. system.rewrite(f,1);
  1807. end;
  1808. procedure tbufferedfile.flush;
  1809. var
  1810. {$ifdef FPC}
  1811. count : longint;
  1812. {$else}
  1813. count : integer;
  1814. {$endif}
  1815. begin
  1816. if iomode=2 then
  1817. begin
  1818. if bufpos=0 then
  1819. exit;
  1820. blockwrite(f,buf^,bufpos)
  1821. end
  1822. else if iomode=1 then
  1823. if buflast=bufpos then
  1824. begin
  1825. blockread(f,buf^,bufsize,count);
  1826. buflast:=count;
  1827. end;
  1828. bufpos:=0;
  1829. end;
  1830. function tbufferedfile.getftime : longint;
  1831. var
  1832. l : longint;
  1833. {$ifdef linux}
  1834. Info : Stat;
  1835. {$endif}
  1836. begin
  1837. {$ifndef linux}
  1838. { this only works if the file is open !! }
  1839. dos.getftime(f,l);
  1840. {$else}
  1841. Fstat(f,Info);
  1842. l:=info.mtime;
  1843. {$endif}
  1844. getftime:=l;
  1845. end;
  1846. function tbufferedfile.getsize : longint;
  1847. begin
  1848. getsize:=filesize(f);
  1849. end;
  1850. procedure tbufferedfile.seek(l : longint);
  1851. begin
  1852. if iomode=2 then
  1853. begin
  1854. flush;
  1855. system.seek(f,l);
  1856. end
  1857. else if iomode=1 then
  1858. begin
  1859. { forces a reload }
  1860. bufpos:=buflast;
  1861. system.seek(f,l);
  1862. flush;
  1863. end;
  1864. end;
  1865. type
  1866. {$ifdef tp}
  1867. bytearray1 = array [1..65535] of byte;
  1868. {$else}
  1869. bytearray1 = array [1..10000000] of byte;
  1870. {$endif}
  1871. procedure tbufferedfile.read_data(var data;bytes : longint;var count : longint);
  1872. var
  1873. p : pchar;
  1874. c,i : longint;
  1875. begin
  1876. p:=pchar(@data);
  1877. count:=0;
  1878. while bytes-count>0 do
  1879. begin
  1880. if bytes-count>buflast-bufpos then
  1881. begin
  1882. move((buf+bufpos)^,(p+count)^,buflast-bufpos);
  1883. inc(count,buflast-bufpos);
  1884. bufpos:=buflast;
  1885. flush;
  1886. { can't we read anything ? }
  1887. if bufpos=buflast then
  1888. break;
  1889. end
  1890. else
  1891. begin
  1892. move((buf+bufpos)^,(p+count)^,bytes-count);
  1893. inc(bufpos,bytes-count);
  1894. count:=bytes;
  1895. break;
  1896. end;
  1897. end;
  1898. if do_crc then
  1899. begin
  1900. c:=crc;
  1901. for i:=1 to bytes do
  1902. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1903. crc:=c;
  1904. end;
  1905. end;
  1906. procedure tbufferedfile.write_data(var data;count : longint);
  1907. var
  1908. c,i : longint;
  1909. begin
  1910. if bufpos+count>bufsize then
  1911. flush;
  1912. move(data,(buf+bufpos)^,count);
  1913. inc(bufpos,count);
  1914. if do_crc then
  1915. begin
  1916. c:=crc;
  1917. for i:=1 to count do
  1918. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1919. crc:=c;
  1920. end;
  1921. end;
  1922. function tbufferedfile.getcrc : longint;
  1923. begin
  1924. getcrc:=crc xor crcseed;
  1925. end;
  1926. procedure tbufferedfile.write_string(const s : string);
  1927. begin
  1928. if bufpos+length(s)>bufsize then
  1929. flush;
  1930. { why is there not CRC here ??? }
  1931. move(s[1],(buf+bufpos)^,length(s));
  1932. inc(bufpos,length(s));
  1933. { should be
  1934. write_data(s[1],length(s)); }
  1935. end;
  1936. procedure tbufferedfile.write_pchar(p : pchar);
  1937. var
  1938. l : longint;
  1939. begin
  1940. l:=strlen(p);
  1941. if l>=bufsize then
  1942. do_internalerror(222);
  1943. { why is there not CRC here ???}
  1944. if bufpos+l>bufsize then
  1945. flush;
  1946. move(p^,(buf+bufpos)^,l);
  1947. inc(bufpos,l);
  1948. { should be
  1949. write_data(p^,l); }
  1950. end;
  1951. procedure tbufferedfile.write_byte(b : byte);
  1952. begin
  1953. write_data(b,sizeof(byte));
  1954. end;
  1955. procedure tbufferedfile.write_long(l : longint);
  1956. var
  1957. w1,w2 : word;
  1958. begin
  1959. if change_endian then
  1960. begin
  1961. w1:=l and $ffff;
  1962. w2:=l shr 16;
  1963. l:=swap(w2)+(longint(swap(w1)) shl 16);
  1964. end;
  1965. write_data(l,sizeof(longint));
  1966. end;
  1967. procedure tbufferedfile.write_word(w : word);
  1968. begin
  1969. if change_endian then
  1970. begin
  1971. w:=swap(w);
  1972. end;
  1973. write_data(w,sizeof(word));
  1974. end;
  1975. procedure tbufferedfile.write_double(d : double);
  1976. begin
  1977. write_data(d,sizeof(double));
  1978. end;
  1979. function tbufferedfile.getpath : string;
  1980. begin
  1981. {$ifdef dummy}
  1982. getpath:=strpas(filerec(f).name);
  1983. {$endif}
  1984. getpath:='';
  1985. end;
  1986. procedure tbufferedfile.close;
  1987. begin
  1988. if iomode<>0 then
  1989. begin
  1990. flush;
  1991. system.close(f);
  1992. freemem(buf,bufsize);
  1993. buf:=nil;
  1994. iomode:=0;
  1995. end;
  1996. end;
  1997. procedure tbufferedfile.tempclose;
  1998. begin
  1999. if iomode<>0 then
  2000. begin
  2001. temppos:=system.filepos(f);
  2002. tempmode:=iomode;
  2003. tempclosed:=true;
  2004. system.close(f);
  2005. iomode:=0;
  2006. end
  2007. else
  2008. tempclosed:=false;
  2009. end;
  2010. procedure tbufferedfile.tempreopen;
  2011. var
  2012. ofm : byte;
  2013. begin
  2014. if tempclosed then
  2015. begin
  2016. case tempmode of
  2017. 1 : begin
  2018. ofm:=filemode;
  2019. iomode:=1;
  2020. filemode:=0;
  2021. system.reset(f,1);
  2022. filemode:=ofm;
  2023. end;
  2024. 2 : begin
  2025. iomode:=2;
  2026. system.rewrite(f,1);
  2027. end;
  2028. end;
  2029. system.seek(f,temppos);
  2030. tempclosed:=false;
  2031. end;
  2032. end;
  2033. {$endif BUFFEREDFILE}
  2034. end.
  2035. {
  2036. $Log$
  2037. Revision 1.2 2000-07-13 11:32:38 michael
  2038. + removed logs
  2039. }