cobjects.pas 55 KB

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