cobjects.pas 52 KB

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