cobjects.pas 51 KB

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