cobjects.pas 56 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099
  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. destructor done;virtual;
  137. procedure setname(const n:string);virtual;
  138. function name:string;virtual;
  139. end;
  140. Pdictionaryhasharray=^Tdictionaryhasharray;
  141. Tdictionaryhasharray=array[-hasharraysize..hasharraysize] of Pnamedindexobject;
  142. Tnamedindexcallback = procedure(p:Pnamedindexobject);
  143. Pdictionary=^Tdictionary;
  144. Tdictionary=object(Tobject)
  145. replace_existing : boolean;
  146. constructor init;
  147. destructor done;virtual;
  148. procedure usehash;
  149. procedure clear;
  150. function empty: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:=-1;
  838. _name:=stringdup(n);
  839. end;
  840. destructor Tnamedindexobject.done;
  841. begin
  842. stringdispose(_name);
  843. end;
  844. procedure Tnamedindexobject.setname(const n:string);
  845. begin
  846. if speedvalue=-1 then
  847. begin
  848. if assigned(_name) then
  849. stringdispose(_name);
  850. _name:=stringdup(n);
  851. end;
  852. end;
  853. function Tnamedindexobject.name:string;
  854. begin
  855. if assigned(_name) then
  856. name:=_name^
  857. else
  858. name:='';
  859. end;
  860. {****************************************************************************
  861. TDICTIONARY
  862. ****************************************************************************}
  863. constructor Tdictionary.init;
  864. begin
  865. inherited init;
  866. replace_existing:=false;
  867. end;
  868. procedure Tdictionary.usehash;
  869. begin
  870. if not(assigned(root)) and
  871. not(assigned(hasharray)) then
  872. begin
  873. new(hasharray);
  874. fillchar(hasharray^,sizeof(hasharray^),0);
  875. end;
  876. end;
  877. destructor Tdictionary.done;
  878. begin
  879. clear;
  880. if assigned(hasharray) then
  881. dispose(hasharray);
  882. end;
  883. procedure Tdictionary.cleartree(obj:Pnamedindexobject);
  884. begin
  885. if assigned(obj^.left) then
  886. cleartree(obj^.left);
  887. if assigned(obj^.right) then
  888. cleartree(obj^.right);
  889. dispose(obj,done);
  890. obj:=nil;
  891. end;
  892. procedure Tdictionary.clear;
  893. var
  894. w : longint;
  895. begin
  896. if assigned(root) then
  897. cleartree(root);
  898. if assigned(hasharray) then
  899. for w:=-hasharraysize to hasharraysize do
  900. if assigned(hasharray^[w]) then
  901. cleartree(hasharray^[w]);
  902. end;
  903. function Tdictionary.empty:boolean;
  904. var
  905. w : longint;
  906. begin
  907. if assigned(hasharray) then
  908. begin
  909. empty:=false;
  910. for w:=-hasharraysize to hasharraysize do
  911. if assigned(hasharray^[w]) then
  912. exit;
  913. empty:=true;
  914. end
  915. else
  916. empty:=(root=nil);
  917. end;
  918. procedure Tdictionary.foreach(proc2call:Tnamedindexcallback);
  919. procedure a(p:Pnamedindexobject);
  920. begin
  921. proc2call(p);
  922. if assigned(p^.left) then
  923. a(p^.left);
  924. if assigned(p^.right) then
  925. a(p^.right);
  926. end;
  927. var
  928. i : longint;
  929. begin
  930. if assigned(hasharray) then
  931. begin
  932. for i:=-hasharraysize to hasharraysize do
  933. if assigned(hasharray^[i]) then
  934. a(hasharray^[i]);
  935. end
  936. else
  937. if assigned(root) then
  938. a(root);
  939. end;
  940. function Tdictionary.insert(obj:Pnamedindexobject):Pnamedindexobject;
  941. begin
  942. obj^.speedvalue:=getspeedvalue(obj^._name^);
  943. if assigned(hasharray) then
  944. insert:=insertnode(obj,hasharray^[obj^.speedvalue mod hasharraysize])
  945. else
  946. insert:=insertnode(obj,root);
  947. end;
  948. function tdictionary.insertnode(newnode:Pnamedindexobject;var currnode:Pnamedindexobject):Pnamedindexobject;
  949. var
  950. s1,s2:^string;
  951. begin
  952. if currnode=nil then
  953. begin
  954. currnode:=newnode;
  955. insertnode:=currnode;
  956. end
  957. { first check speedvalue, to allow a fast insert }
  958. else
  959. if currnode^.speedvalue>newnode^.speedvalue then
  960. insertnode:=insertnode(newnode,currnode^.right)
  961. else
  962. if currnode^.speedvalue<newnode^.speedvalue then
  963. insertnode:=insertnode(newnode,currnode^.left)
  964. else
  965. begin
  966. new(s1);
  967. new(s2);
  968. s1^:=currnode^._name^;
  969. s2^:=newnode^._name^;
  970. if s1^>s2^ then
  971. begin
  972. dispose(s2);
  973. dispose(s1);
  974. insertnode:=insertnode(newnode,currnode^.right);
  975. end
  976. else
  977. if s1^<s2^ then
  978. begin
  979. dispose(s2);
  980. dispose(s1);
  981. insertnode:=insertnode(newnode,currnode^.left);
  982. end
  983. else
  984. begin
  985. dispose(s2);
  986. dispose(s1);
  987. if replace_existing and
  988. assigned(currnode) then
  989. begin
  990. newnode^.left:=currnode^.left;
  991. newnode^.right:=currnode^.right;
  992. currnode:=newnode;
  993. insertnode:=newnode;
  994. end
  995. else
  996. insertnode:=currnode;
  997. end;
  998. end;
  999. end;
  1000. procedure tdictionary.inserttree(currtree,currroot:Pnamedindexobject);
  1001. begin
  1002. if assigned(currtree) then
  1003. begin
  1004. inserttree(currtree^.left,currroot);
  1005. inserttree(currtree^.right,currroot);
  1006. currtree^.right:=nil;
  1007. currtree^.left:=nil;
  1008. insertnode(currtree,currroot);
  1009. end;
  1010. end;
  1011. function tdictionary.rename(const olds,news : string):Pnamedindexobject;
  1012. var
  1013. spdval : longint;
  1014. lasthp,
  1015. hp,hp2,hp3 : Pnamedindexobject;
  1016. begin
  1017. spdval:=getspeedvalue(olds);
  1018. if assigned(hasharray) then
  1019. hp:=hasharray^[spdval mod hasharraysize]
  1020. else
  1021. hp:=root;
  1022. lasthp:=nil;
  1023. while assigned(hp) do
  1024. begin
  1025. if spdval>hp^.speedvalue then
  1026. begin
  1027. lasthp:=hp;
  1028. hp:=hp^.left
  1029. end
  1030. else
  1031. if spdval<hp^.speedvalue then
  1032. begin
  1033. lasthp:=hp;
  1034. hp:=hp^.right
  1035. end
  1036. else
  1037. begin
  1038. if (hp^.name=olds) then
  1039. begin
  1040. { get in hp2 the replacer for the root or hasharr }
  1041. hp2:=hp^.left;
  1042. hp3:=hp^.right;
  1043. if not assigned(hp2) then
  1044. begin
  1045. hp2:=hp^.right;
  1046. hp3:=hp^.left;
  1047. end;
  1048. { remove entry from the tree }
  1049. if assigned(lasthp) then
  1050. begin
  1051. if lasthp^.left=hp then
  1052. lasthp^.left:=hp2
  1053. else
  1054. lasthp^.right:=hp2;
  1055. end
  1056. else
  1057. begin
  1058. if assigned(hasharray) then
  1059. hasharray^[spdval mod hasharraysize]:=hp2
  1060. else
  1061. root:=hp2;
  1062. end;
  1063. { reinsert the hp3 in the tree from hp2 }
  1064. inserttree(hp3,hp2);
  1065. { reset node with new values }
  1066. stringdispose(hp^._name);
  1067. hp^._name:=stringdup(news);
  1068. hp^.speedvalue:=getspeedvalue(news);
  1069. hp^.left:=nil;
  1070. hp^.right:=nil;
  1071. { reinsert }
  1072. if assigned(hasharray) then
  1073. rename:=insertnode(hp,hasharray^[hp^.speedvalue mod hasharraysize])
  1074. else
  1075. rename:=insertnode(hp,root);
  1076. exit;
  1077. end
  1078. else
  1079. if olds>hp^.name then
  1080. begin
  1081. lasthp:=hp;
  1082. hp:=hp^.left
  1083. end
  1084. else
  1085. begin
  1086. lasthp:=hp;
  1087. hp:=hp^.right;
  1088. end;
  1089. end;
  1090. end;
  1091. end;
  1092. function Tdictionary.delete(const s:string):Pnamedindexobject;
  1093. var p,speedvalue:longint;
  1094. n:Pnamedindexobject;
  1095. procedure insert_right_bottom(var root,Atree:Pnamedindexobject);
  1096. begin
  1097. while root^.right<>nil do
  1098. root:=root^.right;
  1099. root^.right:=Atree;
  1100. end;
  1101. function delete_from_tree(root:Pnamedindexobject):Pnamedindexobject;
  1102. type leftright=(left,right);
  1103. var lr:leftright;
  1104. oldroot:Pnamedindexobject;
  1105. begin
  1106. oldroot:=nil;
  1107. while (root<>nil) and (root^.speedvalue<>speedvalue) do
  1108. begin
  1109. oldroot:=root;
  1110. if speedvalue<root^.speedvalue then
  1111. begin
  1112. root:=root^.right;
  1113. lr:=right;
  1114. end
  1115. else
  1116. begin
  1117. root:=root^.left;
  1118. lr:=left;
  1119. end;
  1120. end;
  1121. while (root<>nil) and (root^._name^<>s) do
  1122. begin
  1123. oldroot:=root;
  1124. if s<root^._name^ then
  1125. begin
  1126. root:=root^.right;
  1127. lr:=right;
  1128. end
  1129. else
  1130. begin
  1131. root:=root^.left;
  1132. lr:=left;
  1133. end;
  1134. end;
  1135. if (oldroot=nil) or (root=nil) then
  1136. runerror(218); {Internalerror is not available...}
  1137. if root^.left<>nil then
  1138. begin
  1139. {Now the node pointing to root must point to the left
  1140. subtree of root. The right subtree of root must be
  1141. connected to the right bottom of the left subtree.}
  1142. if lr=left then
  1143. oldroot^.left:=root^.left
  1144. else
  1145. oldroot^.right:=root^.left;
  1146. if root^.right<>nil then
  1147. insert_right_bottom(root^.left,root^.right);
  1148. end
  1149. else
  1150. {There is no left subtree. So we can just replace the node to
  1151. delete with the right subtree.}
  1152. if lr=left then
  1153. oldroot^.left:=root^.right
  1154. else
  1155. oldroot^.right:=root^.right;
  1156. delete_from_tree:=root;
  1157. end;
  1158. begin
  1159. speedvalue:=getspeedvalue(s);
  1160. n:=root;
  1161. if assigned(hasharray) then
  1162. begin
  1163. {First, check if the node to delete directly located under
  1164. the hasharray.}
  1165. p:=speedvalue mod hasharraysize;
  1166. n:=hasharray^[p];
  1167. if (n<>nil) and (n^.speedvalue=speedvalue) and
  1168. (n^._name^=s) then
  1169. begin
  1170. {The node to delete is directly located under the
  1171. hasharray. Make the hasharray point to the left
  1172. subtree of the node and place the right subtree on
  1173. the right-bottom of the left subtree.}
  1174. if n^.left<>nil then
  1175. begin
  1176. hasharray^[p]:=n^.left;
  1177. if n^.right<>nil then
  1178. insert_right_bottom(n^.left,n^.right);
  1179. end
  1180. else
  1181. hasharray^[p]:=n^.right;
  1182. delete:=n;
  1183. exit;
  1184. end;
  1185. end
  1186. else
  1187. begin
  1188. {First check if the node to delete is the root.}
  1189. if (root<>nil) and (n^.speedvalue=speedvalue)
  1190. and (n^._name^=s) then
  1191. begin
  1192. if n^.left<>nil then
  1193. begin
  1194. root:=n^.left;
  1195. if n^.right<>nil then
  1196. insert_right_bottom(n^.left,n^.right);
  1197. end
  1198. else
  1199. root:=n^.right;
  1200. delete:=n;
  1201. exit;
  1202. end;
  1203. end;
  1204. delete:=delete_from_tree(n);
  1205. end;
  1206. function Tdictionary.search(const s:string):Pnamedindexobject;
  1207. begin
  1208. search:=speedsearch(s,getspeedvalue(s));
  1209. end;
  1210. function Tdictionary.speedsearch(const s:string;speedvalue:longint):Pnamedindexobject;
  1211. var
  1212. newnode:Pnamedindexobject;
  1213. begin
  1214. if assigned(hasharray) then
  1215. newnode:=hasharray^[speedvalue mod hasharraysize]
  1216. else
  1217. newnode:=root;
  1218. while assigned(newnode) do
  1219. begin
  1220. if speedvalue>newnode^.speedvalue then
  1221. newnode:=newnode^.left
  1222. else
  1223. if speedvalue<newnode^.speedvalue then
  1224. newnode:=newnode^.right
  1225. else
  1226. begin
  1227. if (newnode^._name^=s) then
  1228. begin
  1229. speedsearch:=newnode;
  1230. exit;
  1231. end
  1232. else
  1233. if s>newnode^._name^ then
  1234. newnode:=newnode^.left
  1235. else
  1236. newnode:=newnode^.right;
  1237. end;
  1238. end;
  1239. speedsearch:=nil;
  1240. end;
  1241. {****************************************************************************
  1242. tdynamicarray
  1243. ****************************************************************************}
  1244. constructor tdynamicarray.init(Aelemlen,Agrow:longint);
  1245. begin
  1246. inherited init;
  1247. elemlen:=Aelemlen;
  1248. growcount:=Agrow;
  1249. grow;
  1250. end;
  1251. function tdynamicarray.size:longint;
  1252. begin
  1253. size:=limit*elemlen;
  1254. end;
  1255. function tdynamicarray.usedsize:longint;
  1256. begin
  1257. usedsize:=count*elemlen;
  1258. end;
  1259. procedure tdynamicarray.grow;
  1260. var
  1261. osize : longint;
  1262. odata : pchar;
  1263. begin
  1264. osize:=size;
  1265. odata:=data;
  1266. inc(limit,growcount);
  1267. getmem(data,size);
  1268. if assigned(odata) then
  1269. begin
  1270. move(odata^,data^,osize);
  1271. freemem(odata,osize);
  1272. end;
  1273. fillchar(data[osize],growcount*elemlen,0);
  1274. end;
  1275. procedure tdynamicarray.align(i:longint);
  1276. var
  1277. j : longint;
  1278. begin
  1279. j:=(posn*elemlen mod i);
  1280. if j<>0 then
  1281. begin
  1282. j:=i-j;
  1283. while limit<(posn+j) do
  1284. grow;
  1285. inc(posn,j);
  1286. if (posn>count) then
  1287. count:=posn;
  1288. end;
  1289. end;
  1290. procedure tdynamicarray.seek(i:longint);
  1291. begin
  1292. while limit<i do
  1293. grow;
  1294. posn:=i;
  1295. if (posn>count) then
  1296. count:=posn;
  1297. end;
  1298. procedure tdynamicarray.write(var d;len:longint);
  1299. begin
  1300. while limit<(posn+len) do
  1301. grow;
  1302. move(d,data[posn*elemlen],len*elemlen);
  1303. inc(posn,len);
  1304. if (posn>count) then
  1305. count:=posn;
  1306. end;
  1307. procedure tdynamicarray.read(var d;len:longint);
  1308. begin
  1309. move(data[posn*elemlen],d,len*elemlen);
  1310. inc(posn,len);
  1311. if (posn>count) then
  1312. count:=posn;
  1313. end;
  1314. procedure tdynamicarray.writepos(pos:longint;var d;len:longint);
  1315. begin
  1316. while limit<(pos+len) do
  1317. grow;
  1318. move(d,data[pos*elemlen],len*elemlen);
  1319. posn:=pos+len;
  1320. if (posn>count) then
  1321. count:=posn;
  1322. end;
  1323. procedure tdynamicarray.readpos(pos:longint;var d;len:longint);
  1324. begin
  1325. while limit<(pos+len) do
  1326. grow;
  1327. move(data[pos*elemlen],d,len*elemlen);
  1328. posn:=pos+len;
  1329. if (posn>count) then
  1330. count:=posn;
  1331. end;
  1332. destructor tdynamicarray.done;
  1333. begin
  1334. if assigned(data) then
  1335. freemem(data,size);
  1336. end;
  1337. {$ifdef BUFFEREDFILE}
  1338. {****************************************************************************
  1339. TBUFFEREDFILE
  1340. ****************************************************************************}
  1341. Const
  1342. crcseed = $ffffffff;
  1343. crctable : array[0..255] of longint = (
  1344. $00000000,$77073096,$ee0e612c,$990951ba,$076dc419,$706af48f,
  1345. $e963a535,$9e6495a3,$0edb8832,$79dcb8a4,$e0d5e91e,$97d2d988,
  1346. $09b64c2b,$7eb17cbd,$e7b82d07,$90bf1d91,$1db71064,$6ab020f2,
  1347. $f3b97148,$84be41de,$1adad47d,$6ddde4eb,$f4d4b551,$83d385c7,
  1348. $136c9856,$646ba8c0,$fd62f97a,$8a65c9ec,$14015c4f,$63066cd9,
  1349. $fa0f3d63,$8d080df5,$3b6e20c8,$4c69105e,$d56041e4,$a2677172,
  1350. $3c03e4d1,$4b04d447,$d20d85fd,$a50ab56b,$35b5a8fa,$42b2986c,
  1351. $dbbbc9d6,$acbcf940,$32d86ce3,$45df5c75,$dcd60dcf,$abd13d59,
  1352. $26d930ac,$51de003a,$c8d75180,$bfd06116,$21b4f4b5,$56b3c423,
  1353. $cfba9599,$b8bda50f,$2802b89e,$5f058808,$c60cd9b2,$b10be924,
  1354. $2f6f7c87,$58684c11,$c1611dab,$b6662d3d,$76dc4190,$01db7106,
  1355. $98d220bc,$efd5102a,$71b18589,$06b6b51f,$9fbfe4a5,$e8b8d433,
  1356. $7807c9a2,$0f00f934,$9609a88e,$e10e9818,$7f6a0dbb,$086d3d2d,
  1357. $91646c97,$e6635c01,$6b6b51f4,$1c6c6162,$856530d8,$f262004e,
  1358. $6c0695ed,$1b01a57b,$8208f4c1,$f50fc457,$65b0d9c6,$12b7e950,
  1359. $8bbeb8ea,$fcb9887c,$62dd1ddf,$15da2d49,$8cd37cf3,$fbd44c65,
  1360. $4db26158,$3ab551ce,$a3bc0074,$d4bb30e2,$4adfa541,$3dd895d7,
  1361. $a4d1c46d,$d3d6f4fb,$4369e96a,$346ed9fc,$ad678846,$da60b8d0,
  1362. $44042d73,$33031de5,$aa0a4c5f,$dd0d7cc9,$5005713c,$270241aa,
  1363. $be0b1010,$c90c2086,$5768b525,$206f85b3,$b966d409,$ce61e49f,
  1364. $5edef90e,$29d9c998,$b0d09822,$c7d7a8b4,$59b33d17,$2eb40d81,
  1365. $b7bd5c3b,$c0ba6cad,$edb88320,$9abfb3b6,$03b6e20c,$74b1d29a,
  1366. $ead54739,$9dd277af,$04db2615,$73dc1683,$e3630b12,$94643b84,
  1367. $0d6d6a3e,$7a6a5aa8,$e40ecf0b,$9309ff9d,$0a00ae27,$7d079eb1,
  1368. $f00f9344,$8708a3d2,$1e01f268,$6906c2fe,$f762575d,$806567cb,
  1369. $196c3671,$6e6b06e7,$fed41b76,$89d32be0,$10da7a5a,$67dd4acc,
  1370. $f9b9df6f,$8ebeeff9,$17b7be43,$60b08ed5,$d6d6a3e8,$a1d1937e,
  1371. $38d8c2c4,$4fdff252,$d1bb67f1,$a6bc5767,$3fb506dd,$48b2364b,
  1372. $d80d2bda,$af0a1b4c,$36034af6,$41047a60,$df60efc3,$a867df55,
  1373. $316e8eef,$4669be79,$cb61b38c,$bc66831a,$256fd2a0,$5268e236,
  1374. $cc0c7795,$bb0b4703,$220216b9,$5505262f,$c5ba3bbe,$b2bd0b28,
  1375. $2bb45a92,$5cb36a04,$c2d7ffa7,$b5d0cf31,$2cd99e8b,$5bdeae1d,
  1376. $9b64c2b0,$ec63f226,$756aa39c,$026d930a,$9c0906a9,$eb0e363f,
  1377. $72076785,$05005713,$95bf4a82,$e2b87a14,$7bb12bae,$0cb61b38,
  1378. $92d28e9b,$e5d5be0d,$7cdcefb7,$0bdbdf21,$86d3d2d4,$f1d4e242,
  1379. $68ddb3f8,$1fda836e,$81be16cd,$f6b9265b,$6fb077e1,$18b74777,
  1380. $88085ae6,$ff0f6a70,$66063bca,$11010b5c,$8f659eff,$f862ae69,
  1381. $616bffd3,$166ccf45,$a00ae278,$d70dd2ee,$4e048354,$3903b3c2,
  1382. $a7672661,$d06016f7,$4969474d,$3e6e77db,$aed16a4a,$d9d65adc,
  1383. $40df0b66,$37d83bf0,$a9bcae53,$debb9ec5,$47b2cf7f,$30b5ffe9,
  1384. $bdbdf21c,$cabac28a,$53b39330,$24b4a3a6,$bad03605,$cdd70693,
  1385. $54de5729,$23d967bf,$b3667a2e,$c4614ab8,$5d681b02,$2a6f2b94,
  1386. $b40bbe37,$c30c8ea1,$5a05df1b,$2d02ef8d);
  1387. constructor tbufferedfile.init(const filename : string;_bufsize : longint);
  1388. begin
  1389. inherited init;
  1390. assign(f,filename);
  1391. bufsize:=_bufsize;
  1392. clear_crc;
  1393. end;
  1394. destructor tbufferedfile.done;
  1395. begin
  1396. close;
  1397. end;
  1398. procedure tbufferedfile.clear_crc;
  1399. begin
  1400. crc:=crcseed;
  1401. end;
  1402. procedure tbufferedfile.setbuf(p : pchar;s : longint);
  1403. begin
  1404. flush;
  1405. freemem(buf,bufsize);
  1406. bufsize:=s;
  1407. buf:=p;
  1408. end;
  1409. function tbufferedfile.reset:boolean;
  1410. var
  1411. ofm : byte;
  1412. begin
  1413. ofm:=filemode;
  1414. iomode:=1;
  1415. getmem(buf,bufsize);
  1416. filemode:=0;
  1417. {$I-}
  1418. system.reset(f,1);
  1419. {$I+}
  1420. reset:=(ioresult=0);
  1421. filemode:=ofm;
  1422. end;
  1423. procedure tbufferedfile.rewrite;
  1424. begin
  1425. iomode:=2;
  1426. getmem(buf,bufsize);
  1427. system.rewrite(f,1);
  1428. end;
  1429. procedure tbufferedfile.flush;
  1430. var
  1431. {$ifdef FPC}
  1432. count : longint;
  1433. {$else}
  1434. count : integer;
  1435. {$endif}
  1436. begin
  1437. if iomode=2 then
  1438. begin
  1439. if bufpos=0 then
  1440. exit;
  1441. blockwrite(f,buf^,bufpos)
  1442. end
  1443. else if iomode=1 then
  1444. if buflast=bufpos then
  1445. begin
  1446. blockread(f,buf^,bufsize,count);
  1447. buflast:=count;
  1448. end;
  1449. bufpos:=0;
  1450. end;
  1451. function tbufferedfile.getftime : longint;
  1452. var
  1453. l : longint;
  1454. {$ifdef linux}
  1455. Info : Stat;
  1456. {$endif}
  1457. begin
  1458. {$ifndef linux}
  1459. { this only works if the file is open !! }
  1460. dos.getftime(f,l);
  1461. {$else}
  1462. Fstat(f,Info);
  1463. l:=info.mtime;
  1464. {$endif}
  1465. getftime:=l;
  1466. end;
  1467. function tbufferedfile.getsize : longint;
  1468. begin
  1469. getsize:=filesize(f);
  1470. end;
  1471. procedure tbufferedfile.seek(l : longint);
  1472. begin
  1473. if iomode=2 then
  1474. begin
  1475. flush;
  1476. system.seek(f,l);
  1477. end
  1478. else if iomode=1 then
  1479. begin
  1480. { forces a reload }
  1481. bufpos:=buflast;
  1482. system.seek(f,l);
  1483. flush;
  1484. end;
  1485. end;
  1486. type
  1487. {$ifdef tp}
  1488. bytearray1 = array [1..65535] of byte;
  1489. {$else}
  1490. bytearray1 = array [1..10000000] of byte;
  1491. {$endif}
  1492. procedure tbufferedfile.read_data(var data;bytes : longint;var count : longint);
  1493. var
  1494. p : pchar;
  1495. c,i : longint;
  1496. begin
  1497. p:=pchar(@data);
  1498. count:=0;
  1499. while bytes-count>0 do
  1500. begin
  1501. if bytes-count>buflast-bufpos then
  1502. begin
  1503. move((buf+bufpos)^,(p+count)^,buflast-bufpos);
  1504. inc(count,buflast-bufpos);
  1505. bufpos:=buflast;
  1506. flush;
  1507. { can't we read anything ? }
  1508. if bufpos=buflast then
  1509. break;
  1510. end
  1511. else
  1512. begin
  1513. move((buf+bufpos)^,(p+count)^,bytes-count);
  1514. inc(bufpos,bytes-count);
  1515. count:=bytes;
  1516. break;
  1517. end;
  1518. end;
  1519. if do_crc then
  1520. begin
  1521. c:=crc;
  1522. for i:=1 to bytes do
  1523. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1524. crc:=c;
  1525. end;
  1526. end;
  1527. procedure tbufferedfile.write_data(var data;count : longint);
  1528. var
  1529. c,i : longint;
  1530. begin
  1531. if bufpos+count>bufsize then
  1532. flush;
  1533. move(data,(buf+bufpos)^,count);
  1534. inc(bufpos,count);
  1535. if do_crc then
  1536. begin
  1537. c:=crc;
  1538. for i:=1 to count do
  1539. c:=(c shr 8) xor crctable[byte(c) xor (bytearray1(data)[i])];
  1540. crc:=c;
  1541. end;
  1542. end;
  1543. function tbufferedfile.getcrc : longint;
  1544. begin
  1545. getcrc:=crc xor crcseed;
  1546. end;
  1547. procedure tbufferedfile.write_string(const s : string);
  1548. begin
  1549. if bufpos+length(s)>bufsize then
  1550. flush;
  1551. { why is there not CRC here ??? }
  1552. move(s[1],(buf+bufpos)^,length(s));
  1553. inc(bufpos,length(s));
  1554. { should be
  1555. write_data(s[1],length(s)); }
  1556. end;
  1557. procedure tbufferedfile.write_pchar(p : pchar);
  1558. var
  1559. l : longint;
  1560. begin
  1561. l:=strlen(p);
  1562. if l>=bufsize then
  1563. runerror(222);
  1564. { why is there not CRC here ???}
  1565. if bufpos+l>bufsize then
  1566. flush;
  1567. move(p^,(buf+bufpos)^,l);
  1568. inc(bufpos,l);
  1569. { should be
  1570. write_data(p^,l); }
  1571. end;
  1572. procedure tbufferedfile.write_byte(b : byte);
  1573. begin
  1574. write_data(b,sizeof(byte));
  1575. end;
  1576. procedure tbufferedfile.write_long(l : longint);
  1577. var
  1578. w1,w2 : word;
  1579. begin
  1580. if change_endian then
  1581. begin
  1582. w1:=l and $ffff;
  1583. w2:=l shr 16;
  1584. l:=swap(w2)+(longint(swap(w1)) shl 16);
  1585. end;
  1586. write_data(l,sizeof(longint));
  1587. end;
  1588. procedure tbufferedfile.write_word(w : word);
  1589. begin
  1590. if change_endian then
  1591. begin
  1592. w:=swap(w);
  1593. end;
  1594. write_data(w,sizeof(word));
  1595. end;
  1596. procedure tbufferedfile.write_double(d : double);
  1597. begin
  1598. write_data(d,sizeof(double));
  1599. end;
  1600. function tbufferedfile.getpath : string;
  1601. begin
  1602. {$ifdef dummy}
  1603. getpath:=strpas(filerec(f).name);
  1604. {$endif}
  1605. getpath:='';
  1606. end;
  1607. procedure tbufferedfile.close;
  1608. begin
  1609. if iomode<>0 then
  1610. begin
  1611. flush;
  1612. system.close(f);
  1613. freemem(buf,bufsize);
  1614. buf:=nil;
  1615. iomode:=0;
  1616. end;
  1617. end;
  1618. procedure tbufferedfile.tempclose;
  1619. begin
  1620. if iomode<>0 then
  1621. begin
  1622. temppos:=system.filepos(f);
  1623. tempmode:=iomode;
  1624. tempclosed:=true;
  1625. system.close(f);
  1626. iomode:=0;
  1627. end
  1628. else
  1629. tempclosed:=false;
  1630. end;
  1631. procedure tbufferedfile.tempreopen;
  1632. var
  1633. ofm : byte;
  1634. begin
  1635. if tempclosed then
  1636. begin
  1637. case tempmode of
  1638. 1 : begin
  1639. ofm:=filemode;
  1640. iomode:=1;
  1641. filemode:=0;
  1642. system.reset(f,1);
  1643. filemode:=ofm;
  1644. end;
  1645. 2 : begin
  1646. iomode:=2;
  1647. system.rewrite(f,1);
  1648. end;
  1649. end;
  1650. system.seek(f,temppos);
  1651. tempclosed:=false;
  1652. end;
  1653. end;
  1654. {$endif BUFFEREDFILE}
  1655. end.
  1656. {
  1657. $Log$
  1658. Revision 1.1 2000-02-28 17:23:58 daniel
  1659. * Current work of symtable integration committed. The symtable can be
  1660. activated by defining 'newst', but doesn't compile yet. Changes in type
  1661. checking and oop are completed. What is left is to write a new
  1662. symtablestack and adapt the parser to use it.
  1663. Revision 1.1 1999/08/05 20:49:15 daniel
  1664. * Use objects unit.
  1665. Revision 1.36 1999/06/23 11:13:20 peter
  1666. * fixed linebreak
  1667. Revision 1.35 1999/06/23 11:07:23 daniel
  1668. * Tdictionary.delete
  1669. Revision 1.33.2.1 1999/06/15 10:12:22 peter
  1670. * fixed inserttree which didn't reset left,right
  1671. Revision 1.33.2.1 1999/06/15 10:12:22 peter
  1672. * fixed inserttree which didn't reset left,right
  1673. Revision 1.33 1999/05/31 23:33:21 peter
  1674. * fixed tdictionary rename which didn't reset left,right when
  1675. reinserting
  1676. Revision 1.32 1999/05/27 19:44:23 peter
  1677. * removed oldasm
  1678. * plabel -> pasmlabel
  1679. * -a switches to source writing automaticly
  1680. * assembler readers OOPed
  1681. * asmsymbol automaticly external
  1682. * jumptables and other label fixes for asm readers
  1683. Revision 1.31 1999/05/21 13:54:59 peter
  1684. * NEWLAB for label as symbol
  1685. Revision 1.30 1999/05/21 10:38:59 peter
  1686. * fixed deleteindex which didn't reset indexnr and set first wrong
  1687. Revision 1.29 1999/05/08 19:47:27 peter
  1688. * indexarray.delete resets pointer after dispose
  1689. Revision 1.28 1999/05/05 10:05:48 florian
  1690. * a delphi compiled compiler recompiles ppc
  1691. Revision 1.27 1999/05/05 09:19:03 florian
  1692. * more fixes to get it with delphi running
  1693. Revision 1.26 1999/04/21 09:43:31 peter
  1694. * storenumber works
  1695. * fixed some typos in double_checksum
  1696. + incompatible types type1 and type2 message (with storenumber)
  1697. Revision 1.25 1999/04/15 10:01:44 peter
  1698. * small update for storenumber
  1699. Revision 1.24 1999/04/14 09:14:47 peter
  1700. * first things to store the symbol/def number in the ppu
  1701. Revision 1.23 1999/04/08 20:59:39 florian
  1702. * fixed problem with default properties which are a class
  1703. * case bug (from the mailing list with -O2) fixed, the
  1704. distance of the case labels can be greater than the positive
  1705. range of a longint => it is now a dword for fpc
  1706. Revision 1.22 1999/03/31 13:55:10 peter
  1707. * assembler inlining working for ag386bin
  1708. Revision 1.21 1999/03/19 16:35:29 pierre
  1709. * Tnamedindexobject done also removed left and right
  1710. Revision 1.20 1999/03/18 20:30:45 peter
  1711. + .a writer
  1712. Revision 1.19 1999/03/01 13:32:00 pierre
  1713. * external used before implemented problem fixed
  1714. Revision 1.18 1999/02/24 00:59:13 peter
  1715. * small updates for ag386bin
  1716. Revision 1.17 1999/01/19 11:00:33 daniel
  1717. + Tdictionary object: Tsymtable will become object(TTdictionary) in the
  1718. future
  1719. + Tnamed_item object: Tsym will become object(Tnamed_item) in the future
  1720. Revision 1.16 1998/11/04 10:11:37 peter
  1721. * ansistring fixes
  1722. Revision 1.15 1998/10/19 18:04:40 peter
  1723. + tstringcontainer.init_no_doubles
  1724. Revision 1.14 1998/09/18 16:03:37 florian
  1725. * some changes to compile with Delphi
  1726. Revision 1.13 1998/08/12 19:28:16 peter
  1727. * better libc support
  1728. Revision 1.12 1998/07/14 14:46:47 peter
  1729. * released NEWINPUT
  1730. Revision 1.11 1998/07/07 11:19:54 peter
  1731. + NEWINPUT for a better inputfile and scanner object
  1732. Revision 1.10 1998/07/01 15:26:59 peter
  1733. * better bufferfile.reset error handling
  1734. Revision 1.9 1998/06/03 23:40:37 peter
  1735. + unlimited file support, release tempclose
  1736. Revision 1.8 1998/05/20 09:42:33 pierre
  1737. + UseTokenInfo now default
  1738. * unit in interface uses and implementation uses gives error now
  1739. * only one error for unknown symbol (uses lastsymknown boolean)
  1740. the problem came from the label code !
  1741. + first inlined procedures and function work
  1742. (warning there might be allowed cases were the result is still wrong !!)
  1743. * UseBrower updated gives a global list of all position of all used symbols
  1744. with switch -gb
  1745. Revision 1.7 1998/05/06 18:36:53 peter
  1746. * tai_section extended with code,data,bss sections and enumerated type
  1747. * ident 'compiled by FPC' moved to pmodules
  1748. * small fix for smartlink
  1749. Revision 1.6 1998/05/06 08:38:37 pierre
  1750. * better position info with UseTokenInfo
  1751. UseTokenInfo greatly simplified
  1752. + added check for changed tree after first time firstpass
  1753. (if we could remove all the cases were it happen
  1754. we could skip all firstpass if firstpasscount > 1)
  1755. Only with ExtDebug
  1756. Revision 1.5 1998/04/30 15:59:40 pierre
  1757. * GDB works again better :
  1758. correct type info in one pass
  1759. + UseTokenInfo for better source position
  1760. * fixed one remaining bug in scanner for line counts
  1761. * several little fixes
  1762. Revision 1.4 1998/04/29 10:33:50 pierre
  1763. + added some code for ansistring (not complete nor working yet)
  1764. * corrected operator overloading
  1765. * corrected nasm output
  1766. + started inline procedures
  1767. + added starstarn : use ** for exponentiation (^ gave problems)
  1768. + started UseTokenInfo cond to get accurate positions
  1769. Revision 1.3 1998/04/27 23:10:28 peter
  1770. + new scanner
  1771. * $makelib -> if smartlink
  1772. * small filename fixes pmodule.setfilename
  1773. * moved import from files.pas -> import.pas
  1774. Revision 1.2 1998/04/07 11:09:04 peter
  1775. + filemode is set correct in tbufferedfile.reset
  1776. }