cobjects.pas 59 KB

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