cobjects.pas 52 KB

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