cobjects.pas 61 KB

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