files.pas 40 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322
  1. {
  2. $Id$
  3. Copyright (c) 1996-98 by Florian Klaempfl
  4. This unit implements an extended file management and the first loading
  5. and searching of the modules (ppufiles)
  6. This program is free software; you can redistribute it and/or modify
  7. it under the terms of the GNU General Public License as published by
  8. the Free Software Foundation; either version 2 of the License, or
  9. (at your option) any later version.
  10. This program is distributed in the hope that it will be useful,
  11. but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. GNU General Public License for more details.
  14. You should have received a copy of the GNU General Public License
  15. along with this program; if not, write to the Free Software
  16. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  17. ****************************************************************************
  18. }
  19. unit files;
  20. {$ifdef TP}
  21. {$V+}
  22. {$endif}
  23. interface
  24. uses
  25. cobjects,globals,ppu;
  26. const
  27. {$ifdef FPC}
  28. maxunits = 1024;
  29. InputFileBufSize=32*1024;
  30. linebufincrease=512;
  31. {$else}
  32. maxunits = 128;
  33. InputFileBufSize=1024;
  34. linebufincrease=64;
  35. {$endif}
  36. type
  37. {$ifdef FPC}
  38. tlongintarr = array[0..1000000] of longint;
  39. {$else}
  40. tlongintarr = array[0..16000] of longint;
  41. {$endif}
  42. plongintarr = ^tlongintarr;
  43. pinputfile = ^tinputfile;
  44. tinputfile = object
  45. path,name : pstring; { path and filename }
  46. next : pinputfile; { next file for reading }
  47. f : file; { current file handle }
  48. is_macro,
  49. endoffile, { still bytes left to read }
  50. closed : boolean; { is the file closed }
  51. buf : pchar; { buffer }
  52. bufstart, { buffer start position in the file }
  53. bufsize, { amount of bytes in the buffer }
  54. maxbufsize : longint; { size in memory for the buffer }
  55. saveinputpointer : pchar; { save fields for scanner variables }
  56. savelastlinepos,
  57. saveline_no : longint;
  58. linebuf : plongintarr; { line buffer to retrieve lines }
  59. maxlinebuf : longint;
  60. ref_count : longint; { to handle the browser refs }
  61. ref_index : longint;
  62. ref_next : pinputfile;
  63. constructor init(const fn:string);
  64. destructor done;
  65. procedure setpos(l:longint);
  66. procedure seekbuf(fpos:longint);
  67. procedure readbuf;
  68. function open:boolean;
  69. procedure close;
  70. procedure tempclose;
  71. function tempopen:boolean;
  72. procedure setmacro(p:pchar;len:longint);
  73. procedure setline(line,linepos:longint);
  74. function getlinestr(l:longint):string;
  75. end;
  76. pfilemanager = ^tfilemanager;
  77. tfilemanager = object
  78. files : pinputfile;
  79. last_ref_index : longint;
  80. constructor init;
  81. destructor done;
  82. procedure register_file(f : pinputfile);
  83. procedure inverse_register_indexes;
  84. function get_file(l:longint) : pinputfile;
  85. function get_file_name(l :longint):string;
  86. function get_file_path(l :longint):string;
  87. end;
  88. type
  89. {$ifndef NEWMAP}
  90. tunitmap = array[0..maxunits-1] of pointer;
  91. punitmap = ^tunitmap;
  92. pmodule = ^tmodule;
  93. {$else NEWMAP}
  94. pmodule = ^tmodule;
  95. tunitmap = array[0..maxunits-1] of pmodule;
  96. punitmap = ^tunitmap;
  97. {$endif NEWMAP}
  98. tmodule = object(tlinkedlist_item)
  99. ppufile : pppufile; { the PPU file }
  100. crc,
  101. flags : longint; { the PPU flags }
  102. compiled, { unit is already compiled }
  103. do_assemble, { only assemble the object, don't recompile }
  104. do_compile, { need to compile the sources }
  105. sources_avail, { if all sources are reachable }
  106. is_unit,
  107. in_second_compile, { is this unit being compiled for the 2nd time? }
  108. in_implementation, { processing the implementation part? }
  109. in_global : boolean; { allow global settings }
  110. map : punitmap; { mapping of all used units }
  111. unitcount : word; { local unit counter }
  112. unit_index : word; { global counter for browser }
  113. globalsymtable, { pointer to the local/static symtable of this unit }
  114. localsymtable : pointer; { pointer to the psymtable of this unit }
  115. scanner : pointer; { scanner object used }
  116. loaded_from : pmodule;
  117. uses_imports : boolean; { Set if the module imports from DLL's.}
  118. imports : plinkedlist;
  119. _exports : plinkedlist;
  120. sourcefiles : pfilemanager;
  121. linksharedlibs,
  122. linkstaticlibs,
  123. linkofiles : tstringcontainer;
  124. used_units : tlinkedlist;
  125. path, { path where the module is find/created }
  126. modulename, { name of the module in uppercase }
  127. objfilename, { fullname of the objectfile }
  128. asmfilename, { fullname of the assemblerfile }
  129. ppufilename, { fullname of the ppufile }
  130. staticlibfilename, { fullname of the static libraryfile }
  131. sharedlibfilename, { fullname of the shared libraryfile }
  132. exefilename, { fullname of the exefile }
  133. asmprefix, { prefix for the smartlink asmfiles }
  134. mainsource : pstring; { name of the main sourcefile }
  135. constructor init(const s:string;_is_unit:boolean);
  136. destructor done;virtual;
  137. procedure reset;
  138. procedure setfilename(const fn:string;allowoutput:boolean);
  139. function openppu:boolean;
  140. function search_unit(const n : string):boolean;
  141. end;
  142. pused_unit = ^tused_unit;
  143. tused_unit = object(tlinkedlist_item)
  144. unitid : word;
  145. name : pstring;
  146. checksum : longint;
  147. loaded : boolean;
  148. in_uses,
  149. in_interface,
  150. is_stab_written : boolean;
  151. u : pmodule;
  152. constructor init(_u : pmodule;intface:boolean);
  153. constructor init_to_load(const n:string;c:longint;intface:boolean);
  154. destructor done;virtual;
  155. end;
  156. var
  157. main_module : pmodule; { Main module of the program }
  158. current_module : pmodule; { Current module which is compiled }
  159. current_ppu : pppufile; { Current ppufile which is read }
  160. global_unit_count : word;
  161. usedunits : tlinkedlist; { Used units for this program }
  162. loaded_units : tlinkedlist; { All loaded units }
  163. implementation
  164. uses
  165. dos,verbose,systems
  166. {$ifndef VER0_99_8}
  167. ,symtable,scanner
  168. {$endif}
  169. ;
  170. {****************************************************************************
  171. TINPUTFILE
  172. ****************************************************************************}
  173. constructor tinputfile.init(const fn:string);
  174. var
  175. p:dirstr;
  176. n:namestr;
  177. e:extstr;
  178. begin
  179. FSplit(fn,p,n,e);
  180. name:=stringdup(n+e);
  181. path:=stringdup(p);
  182. next:=nil;
  183. { file info }
  184. is_macro:=false;
  185. endoffile:=false;
  186. closed:=true;
  187. buf:=nil;
  188. bufstart:=0;
  189. bufsize:=0;
  190. maxbufsize:=InputFileBufSize;
  191. { save fields }
  192. saveinputpointer:=nil;
  193. saveline_no:=0;
  194. savelastlinepos:=0;
  195. { indexing refs }
  196. ref_next:=nil;
  197. ref_count:=0;
  198. ref_index:=0;
  199. { line buffer }
  200. linebuf:=nil;
  201. maxlinebuf:=0;
  202. end;
  203. destructor tinputfile.done;
  204. begin
  205. if not closed then
  206. close;
  207. stringdispose(path);
  208. stringdispose(name);
  209. { free memory }
  210. if assigned(linebuf) then
  211. freemem(linebuf,maxlinebuf shl 2);
  212. end;
  213. procedure tinputfile.setpos(l:longint);
  214. begin
  215. bufstart:=l;
  216. end;
  217. procedure tinputfile.seekbuf(fpos:longint);
  218. begin
  219. if closed then
  220. exit;
  221. seek(f,fpos);
  222. bufstart:=fpos;
  223. bufsize:=0;
  224. end;
  225. procedure tinputfile.readbuf;
  226. {$ifdef TP}
  227. var
  228. w : word;
  229. {$endif}
  230. begin
  231. if is_macro then
  232. endoffile:=true;
  233. if closed then
  234. exit;
  235. inc(bufstart,bufsize);
  236. {$ifdef TP}
  237. blockread(f,buf^,maxbufsize-1,w);
  238. bufsize:=w;
  239. {$else}
  240. blockread(f,buf^,maxbufsize-1,bufsize);
  241. {$endif}
  242. buf[bufsize]:=#0;
  243. endoffile:=not(bufsize=maxbufsize-1);
  244. end;
  245. function tinputfile.open:boolean;
  246. var
  247. ofm : byte;
  248. begin
  249. open:=false;
  250. if not closed then
  251. Close;
  252. ofm:=filemode;
  253. filemode:=0;
  254. Assign(f,path^+name^);
  255. {$I-}
  256. reset(f,1);
  257. {$I+}
  258. filemode:=ofm;
  259. if ioresult<>0 then
  260. exit;
  261. { file }
  262. endoffile:=false;
  263. closed:=false;
  264. Getmem(buf,MaxBufsize);
  265. bufstart:=0;
  266. bufsize:=0;
  267. open:=true;
  268. end;
  269. procedure tinputfile.close;
  270. var
  271. i : word;
  272. begin
  273. if is_macro then
  274. begin
  275. if assigned(buf) then
  276. Freemem(buf,maxbufsize);
  277. buf:=nil;
  278. {is_macro:=false;
  279. still needed for dispose in scanner PM }
  280. closed:=true;
  281. exit;
  282. end;
  283. if not closed then
  284. begin
  285. {$I-}
  286. system.close(f);
  287. {$I+}
  288. i:=ioresult;
  289. closed:=true;
  290. end;
  291. if assigned(buf) then
  292. begin
  293. Freemem(buf,maxbufsize);
  294. buf:=nil;
  295. end;
  296. bufstart:=0;
  297. end;
  298. procedure tinputfile.tempclose;
  299. var
  300. i : word;
  301. begin
  302. if is_macro then
  303. exit;
  304. if not closed then
  305. begin
  306. {$I-}
  307. system.close(f);
  308. {$I+}
  309. i:=ioresult;
  310. Freemem(buf,maxbufsize);
  311. buf:=nil;
  312. closed:=true;
  313. end;
  314. end;
  315. function tinputfile.tempopen:boolean;
  316. var
  317. ofm : byte;
  318. begin
  319. tempopen:=false;
  320. if is_macro then
  321. begin
  322. tempopen:=true;
  323. exit;
  324. end;
  325. if not closed then
  326. exit;
  327. ofm:=filemode;
  328. filemode:=0;
  329. Assign(f,path^+name^);
  330. {$I-}
  331. reset(f,1);
  332. {$I+}
  333. filemode:=ofm;
  334. if ioresult<>0 then
  335. exit;
  336. closed:=false;
  337. { get new mem }
  338. Getmem(buf,maxbufsize);
  339. { restore state }
  340. seek(f,BufStart);
  341. bufsize:=0;
  342. readbuf;
  343. tempopen:=true;
  344. end;
  345. procedure tinputfile.setmacro(p:pchar;len:longint);
  346. begin
  347. { create new buffer }
  348. getmem(buf,len+1);
  349. move(p^,buf^,len);
  350. buf[len]:=#0;
  351. { reset }
  352. bufstart:=0;
  353. bufsize:=len;
  354. maxbufsize:=len+1;
  355. is_macro:=true;
  356. endoffile:=true;
  357. closed:=true;
  358. end;
  359. procedure tinputfile.setline(line,linepos:longint);
  360. var
  361. oldlinebuf : plongintarr;
  362. begin
  363. if line<1 then
  364. exit;
  365. while (line>=maxlinebuf) do
  366. begin
  367. oldlinebuf:=linebuf;
  368. { create new linebuf and move old info }
  369. getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
  370. if assigned(oldlinebuf) then
  371. begin
  372. move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
  373. freemem(oldlinebuf,maxlinebuf shl 2);
  374. end;
  375. fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
  376. inc(maxlinebuf,linebufincrease);
  377. end;
  378. linebuf^[line]:=linepos;
  379. end;
  380. function tinputfile.getlinestr(l:longint):string;
  381. var
  382. c : char;
  383. i,
  384. fpos : longint;
  385. p : pchar;
  386. begin
  387. getlinestr:='';
  388. if l<maxlinebuf then
  389. begin
  390. fpos:=linebuf^[l];
  391. { fpos is set negativ if the line was already written }
  392. { but we still know the correct value }
  393. if fpos<0 then
  394. fpos:=-fpos+1;
  395. if closed then
  396. open;
  397. { in current buf ? }
  398. if (fpos<bufstart) or (fpos>bufstart+bufsize) then
  399. begin
  400. seekbuf(fpos);
  401. readbuf;
  402. end;
  403. { the begin is in the buf now simply read until #13,#10 }
  404. i:=0;
  405. p:=@buf[fpos-bufstart];
  406. repeat
  407. c:=p^;
  408. if c=#0 then
  409. begin
  410. if endoffile then
  411. break;
  412. readbuf;
  413. p:=buf;
  414. c:=p^;
  415. end;
  416. if c in [#10,#13] then
  417. break;
  418. inc(i);
  419. getlinestr[i]:=c;
  420. inc(longint(p));
  421. until (i=255);
  422. getlinestr[0]:=chr(i);
  423. end;
  424. end;
  425. {****************************************************************************
  426. TFILEMANAGER
  427. ****************************************************************************}
  428. constructor tfilemanager.init;
  429. begin
  430. files:=nil;
  431. last_ref_index:=0;
  432. end;
  433. destructor tfilemanager.done;
  434. var
  435. hp : pinputfile;
  436. begin
  437. hp:=files;
  438. while assigned(hp) do
  439. begin
  440. files:=files^.ref_next;
  441. dispose(hp,done);
  442. hp:=files;
  443. end;
  444. last_ref_index:=0;
  445. end;
  446. procedure tfilemanager.register_file(f : pinputfile);
  447. begin
  448. inc(last_ref_index);
  449. f^.ref_next:=files;
  450. f^.ref_index:=last_ref_index;
  451. files:=f;
  452. {$ifdef FPC}
  453. {$ifdef heaptrc}
  454. writeln(stderr,f^.name^,' index ',current_module^.unit_index*100000+f^.ref_index);
  455. {$endif heaptrc}
  456. {$endif FPC}
  457. end;
  458. { this procedure is necessary after loading the
  459. sources files from a PPU file PM }
  460. procedure tfilemanager.inverse_register_indexes;
  461. var
  462. f : pinputfile;
  463. begin
  464. f:=files;
  465. while assigned(f) do
  466. begin
  467. f^.ref_index:=last_ref_index-f^.ref_index+1;
  468. f:=f^.ref_next;
  469. end;
  470. end;
  471. function tfilemanager.get_file(l :longint) : pinputfile;
  472. var
  473. ff : pinputfile;
  474. begin
  475. ff:=files;
  476. while assigned(ff) and (ff^.ref_index<>l) do
  477. ff:=ff^.ref_next;
  478. get_file:=ff;
  479. end;
  480. function tfilemanager.get_file_name(l :longint):string;
  481. var
  482. hp : pinputfile;
  483. begin
  484. hp:=get_file(l);
  485. if assigned(hp) then
  486. get_file_name:=hp^.name^
  487. else
  488. get_file_name:='';
  489. end;
  490. function tfilemanager.get_file_path(l :longint):string;
  491. var
  492. hp : pinputfile;
  493. begin
  494. hp:=get_file(l);
  495. if assigned(hp) then
  496. get_file_path:=hp^.path^
  497. else
  498. get_file_path:='';
  499. end;
  500. {****************************************************************************
  501. TMODULE
  502. ****************************************************************************}
  503. procedure tmodule.setfilename(const fn:string;allowoutput:boolean);
  504. var
  505. p : dirstr;
  506. n : NameStr;
  507. e : ExtStr;
  508. begin
  509. stringdispose(objfilename);
  510. stringdispose(asmfilename);
  511. stringdispose(ppufilename);
  512. stringdispose(staticlibfilename);
  513. stringdispose(sharedlibfilename);
  514. stringdispose(exefilename);
  515. stringdispose(path);
  516. { Create names }
  517. fsplit(fn,p,n,e);
  518. n:=FixFileName(n);
  519. { set path }
  520. path:=stringdup(FixPath(p,false));
  521. { obj,asm,ppu names }
  522. p:=path^;
  523. if AllowOutput then
  524. begin
  525. if (OutputUnitDir<>'') then
  526. p:=OutputUnitDir
  527. else
  528. if (OutputExeDir<>'') then
  529. p:=OutputExeDir;
  530. end;
  531. objfilename:=stringdup(p+n+target_info.objext);
  532. asmfilename:=stringdup(p+n+target_info.asmext);
  533. ppufilename:=stringdup(p+n+target_info.unitext);
  534. { lib and exe could be loaded with a file specified with -o }
  535. if AllowOutput and (OutputFile<>'') then
  536. n:=OutputFile;
  537. staticlibfilename:=stringdup(p+target_os.libprefix+n+target_os.staticlibext);
  538. sharedlibfilename:=stringdup(p+target_os.libprefix+n+target_os.sharedlibext);
  539. { output dir of exe can be specified separatly }
  540. if AllowOutput and (OutputExeDir<>'') then
  541. p:=OutputExeDir
  542. else
  543. p:=path^;
  544. exefilename:=stringdup(p+n+target_os.exeext);
  545. end;
  546. function tmodule.openppu:boolean;
  547. var
  548. objfiletime,
  549. ppufiletime,
  550. asmfiletime : longint;
  551. begin
  552. openppu:=false;
  553. Message1(unit_t_ppu_loading,ppufilename^);
  554. { Get ppufile time (also check if the file exists) }
  555. ppufiletime:=getnamedfiletime(ppufilename^);
  556. if ppufiletime=-1 then
  557. exit;
  558. { Open the ppufile }
  559. Message1(unit_u_ppu_name,ppufilename^);
  560. ppufile:=new(pppufile,init(ppufilename^));
  561. ppufile^.change_endian:=source_os.endian<>target_os.endian;
  562. if not ppufile^.open then
  563. begin
  564. dispose(ppufile,done);
  565. Message(unit_u_ppu_file_too_short);
  566. exit;
  567. end;
  568. { check for a valid PPU file }
  569. if not ppufile^.CheckPPUId then
  570. begin
  571. dispose(ppufile,done);
  572. Message(unit_u_ppu_invalid_header);
  573. exit;
  574. end;
  575. { check for allowed PPU versions }
  576. if not (ppufile^.GetPPUVersion in [15]) then
  577. begin
  578. dispose(ppufile,done);
  579. Message1(unit_u_ppu_invalid_version,tostr(ppufile^.GetPPUVersion));
  580. exit;
  581. end;
  582. { check the target processor }
  583. if ttargetcpu(ppufile^.header.cpu)<>target_cpu then
  584. begin
  585. dispose(ppufile,done);
  586. Message(unit_u_ppu_invalid_processor);
  587. exit;
  588. end;
  589. { check target }
  590. if ttarget(ppufile^.header.target)<>target_info.target then
  591. begin
  592. dispose(ppufile,done);
  593. Message(unit_u_ppu_invalid_target);
  594. exit;
  595. end;
  596. { Load values to be access easier }
  597. flags:=ppufile^.header.flags;
  598. crc:=ppufile^.header.checksum;
  599. { Show Debug info }
  600. Message1(unit_u_ppu_time,filetimestring(ppufiletime));
  601. Message1(unit_u_ppu_flags,tostr(flags));
  602. Message1(unit_u_ppu_crc,tostr(ppufile^.header.checksum));
  603. { check the object and assembler file to see if we need only to
  604. assemble, only if it's not in a library }
  605. do_compile:=false;
  606. if (flags and uf_in_library)=0 then
  607. begin
  608. if ((flags and uf_static_linked)<>0) or
  609. ((flags and uf_smartlink)<>0) then
  610. begin
  611. objfiletime:=getnamedfiletime(staticlibfilename^);
  612. Message2(unit_u_check_time,staticlibfilename^,filetimestring(objfiletime));
  613. if (ppufiletime<0) or (objfiletime<0) or (ppufiletime>objfiletime) then
  614. begin
  615. Message(unit_u_recompile_staticlib_is_older);
  616. do_compile:=true;
  617. exit;
  618. end;
  619. end
  620. else
  621. if (flags and uf_shared_linked)<>0 then
  622. begin
  623. objfiletime:=getnamedfiletime(sharedlibfilename^);
  624. Message2(unit_u_check_time,sharedlibfilename^,filetimestring(objfiletime));
  625. if (ppufiletime<0) or (objfiletime<0) or (ppufiletime>objfiletime) then
  626. begin
  627. Message(unit_u_recompile_sharedlib_is_older);
  628. do_compile:=true;
  629. exit;
  630. end;
  631. end
  632. else
  633. begin
  634. { the objectfile should be newer than the ppu file }
  635. objfiletime:=getnamedfiletime(objfilename^);
  636. Message2(unit_u_check_time,objfilename^,filetimestring(objfiletime));
  637. if (ppufiletime<0) or (objfiletime<0) or (ppufiletime>objfiletime) then
  638. begin
  639. { check if assembler file is older than ppu file }
  640. asmfileTime:=GetNamedFileTime(asmfilename^);
  641. Message2(unit_u_check_time,asmfilename^,filetimestring(asmfiletime));
  642. if (asmfiletime<0) or (ppufiletime>asmfiletime) then
  643. begin
  644. Message(unit_u_recompile_obj_and_asm_older);
  645. do_compile:=true;
  646. exit;
  647. end
  648. else
  649. begin
  650. Message(unit_u_recompile_obj_older_than_asm);
  651. if not(cs_asm_extern in aktglobalswitches) then
  652. begin
  653. do_compile:=true;
  654. exit;
  655. end;
  656. end;
  657. end;
  658. end;
  659. end;
  660. openppu:=true;
  661. end;
  662. function tmodule.search_unit(const n : string):boolean;
  663. var
  664. ext : string[8];
  665. singlepathstring,
  666. unitPath,
  667. filename : string;
  668. found : boolean;
  669. start,i : longint;
  670. Function UnitExists(const ext:string):boolean;
  671. begin
  672. Message1(unit_t_unitsearch,Singlepathstring+filename+ext);
  673. UnitExists:=FileExists(Singlepathstring+FileName+ext);
  674. end;
  675. begin
  676. start:=1;
  677. filename:=FixFileName(n);
  678. unitpath:=UnitSearchPath;
  679. Found:=false;
  680. repeat
  681. { Create current path to check }
  682. i:=pos(';',unitpath);
  683. if i=0 then
  684. i:=length(unitpath)+1;
  685. singlepathstring:=FixPath(copy(unitpath,start,i-start),false);
  686. delete(unitpath,start,i-start+1);
  687. { Check for PPL file }
  688. if not Found then
  689. begin
  690. Found:=UnitExists(target_info.unitlibext);
  691. if Found then
  692. Begin
  693. SetFileName(SinglePathString+FileName,false);
  694. Found:=OpenPPU;
  695. End;
  696. end;
  697. { Check for PPU file }
  698. if not Found then
  699. begin
  700. Found:=UnitExists(target_info.unitext);
  701. if Found then
  702. Begin
  703. SetFileName(SinglePathString+FileName,false);
  704. Found:=OpenPPU;
  705. End;
  706. end;
  707. { Check for Sources }
  708. if not Found then
  709. begin
  710. ppufile:=nil;
  711. do_compile:=true;
  712. {Check for .pp file}
  713. Found:=UnitExists(target_os.sourceext);
  714. if Found then
  715. Ext:=target_os.sourceext
  716. else
  717. begin
  718. {Check for .pas}
  719. Found:=UnitExists(target_os.pasext);
  720. if Found then
  721. Ext:=target_os.pasext;
  722. end;
  723. stringdispose(mainsource);
  724. if Found then
  725. begin
  726. sources_avail:=true;
  727. {Load Filenames when found}
  728. mainsource:=StringDup(SinglePathString+FileName+Ext);
  729. SetFileName(SinglePathString+FileName,false);
  730. end
  731. else
  732. sources_avail:=false;
  733. end;
  734. until Found or (unitpath='');
  735. search_unit:=Found;
  736. end;
  737. procedure tmodule.reset;
  738. begin
  739. {$ifndef VER0_99_8}
  740. if assigned(scanner) then
  741. pscannerfile(scanner)^.invalid:=true;
  742. if assigned(globalsymtable) then
  743. begin
  744. dispose(punitsymtable(globalsymtable),done);
  745. globalsymtable:=nil;
  746. end;
  747. if assigned(localsymtable) then
  748. begin
  749. dispose(punitsymtable(localsymtable),done);
  750. localsymtable:=nil;
  751. end;
  752. {$endif}
  753. if assigned(map) then
  754. begin
  755. dispose(map);
  756. map:=nil;
  757. end;
  758. if assigned(ppufile) then
  759. begin
  760. dispose(ppufile,done);
  761. ppufile:=nil;
  762. end;
  763. sourcefiles^.done;
  764. sourcefiles^.init;
  765. imports^.done;
  766. imports^.init;
  767. used_units.done;
  768. used_units.init;
  769. linkofiles.done;
  770. linkofiles.init_no_double;
  771. linkstaticlibs.done;
  772. linkstaticlibs.init_no_double;
  773. linksharedlibs.done;
  774. linksharedlibs.init_no_double;
  775. uses_imports:=false;
  776. do_assemble:=false;
  777. do_compile:=false;
  778. { sources_avail:=true;
  779. should not be changed PM }
  780. compiled:=false;
  781. in_implementation:=false;
  782. in_global:=true;
  783. loaded_from:=nil;
  784. flags:=0;
  785. crc:=0;
  786. unitcount:=1;
  787. end;
  788. constructor tmodule.init(const s:string;_is_unit:boolean);
  789. var
  790. p : dirstr;
  791. n : namestr;
  792. e : extstr;
  793. begin
  794. FSplit(s,p,n,e);
  795. { Programs have the name program to don't conflict with dup id's }
  796. if _is_unit then
  797. modulename:=stringdup(Upper(n))
  798. else
  799. modulename:=stringdup('PROGRAM');
  800. mainsource:=stringdup(s);
  801. ppufilename:=nil;
  802. objfilename:=nil;
  803. asmfilename:=nil;
  804. staticlibfilename:=nil;
  805. sharedlibfilename:=nil;
  806. exefilename:=nil;
  807. { Dos has the famous 8.3 limit :( }
  808. {$ifdef tp}
  809. asmprefix:=stringdup(FixFileName('as'));
  810. {$else}
  811. {$ifdef go32v2}
  812. asmprefix:=stringdup(FixFileName('as'));
  813. {$else}
  814. {$ifdef OS2}
  815. {Allthough OS/2 supports long filenames I play it safe and
  816. use 8.3 filenames, because this allows the compiler to run
  817. on a FAT partition. (DM)}
  818. asmprefix:=stringdup(FixFileName('as'));
  819. {$else}
  820. asmprefix:=stringdup(FixFileName(n));
  821. {$endif}
  822. {$endif}
  823. {$endif tp}
  824. path:=nil;
  825. setfilename(p+n,true);
  826. used_units.init;
  827. new(sourcefiles,init);
  828. linkofiles.init_no_double;
  829. linkstaticlibs.init_no_double;
  830. linksharedlibs.init_no_double;
  831. ppufile:=nil;
  832. scanner:=nil;
  833. map:=nil;
  834. globalsymtable:=nil;
  835. localsymtable:=nil;
  836. loaded_from:=nil;
  837. flags:=0;
  838. crc:=0;
  839. unitcount:=1;
  840. inc(global_unit_count);
  841. unit_index:=global_unit_count;
  842. do_assemble:=false;
  843. do_compile:=false;
  844. sources_avail:=true;
  845. compiled:=false;
  846. in_second_compile:=false;
  847. in_implementation:=false;
  848. in_global:=true;
  849. is_unit:=_is_unit;
  850. uses_imports:=false;
  851. imports:=new(plinkedlist,init);
  852. { search the PPU file if it is an unit }
  853. if is_unit then
  854. begin
  855. if (not search_unit(modulename^)) and (length(modulename^)>8) then
  856. search_unit(copy(modulename^,1,8));
  857. end;
  858. end;
  859. destructor tmodule.done;
  860. begin
  861. if assigned(map) then
  862. dispose(map);
  863. if assigned(ppufile) then
  864. dispose(ppufile,done);
  865. if assigned(imports) then
  866. dispose(imports,done);
  867. {$ifndef VER0_99_8}
  868. if assigned(scanner) then
  869. pscannerfile(scanner)^.invalid:=true;
  870. {$endif}
  871. if assigned(sourcefiles) then
  872. dispose(sourcefiles,done);
  873. used_units.done;
  874. linkofiles.done;
  875. linkstaticlibs.done;
  876. linksharedlibs.done;
  877. stringdispose(objfilename);
  878. stringdispose(asmfilename);
  879. stringdispose(ppufilename);
  880. stringdispose(staticlibfilename);
  881. stringdispose(sharedlibfilename);
  882. stringdispose(exefilename);
  883. stringdispose(path);
  884. stringdispose(modulename);
  885. stringdispose(mainsource);
  886. stringdispose(asmprefix);
  887. {$ifndef VER0_99_8}
  888. if assigned(globalsymtable) then
  889. dispose(punitsymtable(globalsymtable),done);
  890. if assigned(localsymtable) then
  891. dispose(punitsymtable(localsymtable),done);
  892. {$endif}
  893. inherited done;
  894. end;
  895. {****************************************************************************
  896. TUSED_UNIT
  897. ****************************************************************************}
  898. constructor tused_unit.init(_u : pmodule;intface:boolean);
  899. begin
  900. u:=_u;
  901. in_interface:=intface;
  902. in_uses:=false;
  903. is_stab_written:=false;
  904. loaded:=true;
  905. name:=stringdup(_u^.modulename^);
  906. checksum:=_u^.crc;
  907. unitid:=0;
  908. end;
  909. constructor tused_unit.init_to_load(const n:string;c:longint;intface:boolean);
  910. begin
  911. u:=nil;
  912. in_interface:=intface;
  913. in_uses:=false;
  914. is_stab_written:=false;
  915. loaded:=false;
  916. name:=stringdup(n);
  917. checksum:=c;
  918. unitid:=0;
  919. end;
  920. destructor tused_unit.done;
  921. begin
  922. stringdispose(name);
  923. inherited done;
  924. end;
  925. end.
  926. {
  927. $Log$
  928. Revision 1.68 1998-10-27 10:22:34 florian
  929. + First things for win32 export sections
  930. Revision 1.67 1998/10/26 22:23:29 peter
  931. + fixpath() has an extra option to allow a ./ as path
  932. Revision 1.66 1998/10/19 18:07:11 peter
  933. + external dll_name name func support for linux
  934. Revision 1.65 1998/10/15 12:22:25 pierre
  935. * close include files immediately after end reading
  936. instead of waiting until unit compilation ended !
  937. Revision 1.64 1998/10/14 13:38:19 peter
  938. * fixed path with staticlib/objects in ppufiles
  939. Revision 1.63 1998/10/14 11:02:49 daniel
  940. * Stupid typo fixed.
  941. Revision 1.62 1998/10/14 10:59:37 daniel
  942. * Staticlibfilename now doesn't include path.
  943. Revision 1.61 1998/10/14 10:57:25 daniel
  944. * Dirstr, namestr, extstr.
  945. * $V+ to prevent Peter from forgetting this.
  946. * OS/2 compiler uses 8.3 filenames to support running the compiler on an old
  947. DOS FAT partition.
  948. Revision 1.60 1998/10/14 10:45:07 pierre
  949. * ppu problems for m68k fixed (at least in cross compiling)
  950. * one last memory leak for sysamiga fixed
  951. * the amiga RTL compiles now completely !!
  952. Revision 1.59 1998/10/13 14:01:07 peter
  953. * fixed -al
  954. Revision 1.58 1998/10/12 11:59:00 peter
  955. + show name and date of .o and .s files which the compiler checks
  956. Revision 1.57 1998/10/09 16:36:03 pierre
  957. * some memory leaks specific to usebrowser define fixed
  958. * removed tmodule.implsymtable (was like tmodule.localsymtable)
  959. Revision 1.56 1998/10/09 08:56:26 pierre
  960. * several memory leaks fixed
  961. Revision 1.55 1998/10/08 23:28:54 peter
  962. * -vu shows unit info, -vt shows tried/used files
  963. Revision 1.54 1998/10/08 17:17:19 pierre
  964. * current_module old scanner tagged as invalid if unit is recompiled
  965. + added ppheap for better info on tracegetmem of heaptrc
  966. (adds line column and file index)
  967. * several memory leaks removed ith help of heaptrc !!
  968. Revision 1.53 1998/10/08 13:48:43 peter
  969. * fixed memory leaks for do nothing source
  970. * fixed unit interdependency
  971. Revision 1.52 1998/10/06 22:09:48 peter
  972. * fixed for compiling with 0.99.8 due circular units
  973. Revision 1.51 1998/10/06 17:16:47 pierre
  974. * some memory leaks fixed (thanks to Peter for heaptrc !)
  975. Revision 1.50 1998/09/30 16:43:34 peter
  976. * fixed unit interdependency with circular uses
  977. Revision 1.49 1998/09/28 16:57:20 pierre
  978. * changed all length(p^.value_str^) into str_length(p)
  979. to get it work with and without ansistrings
  980. * changed sourcefiles field of tmodule to a pointer
  981. Revision 1.48 1998/09/24 23:46:34 peter
  982. + outputdir support
  983. Revision 1.47 1998/09/22 17:13:43 pierre
  984. + browsing updated and developed
  985. records and objects fields are also stored
  986. Revision 1.46 1998/09/21 08:45:10 pierre
  987. + added vmt_offset in tobjectdef.write for fututre use
  988. (first steps to have objects without vmt if no virtual !!)
  989. + added fpu_used field for tabstractprocdef :
  990. sets this level to 2 if the functions return with value in FPU
  991. (is then set to correct value at parsing of implementation)
  992. THIS MIGHT refuse some code with FPU expression too complex
  993. that were accepted before and even in some cases
  994. that don't overflow in fact
  995. ( like if f : float; is a forward that finally in implementation
  996. only uses one fpu register !!)
  997. Nevertheless I think that it will improve security on
  998. FPU operations !!
  999. * most other changes only for UseBrowser code
  1000. (added symtable references for record and objects)
  1001. local switch for refs to args and local of each function
  1002. (static symtable still missing)
  1003. UseBrowser still not stable and probably broken by
  1004. the definition hash array !!
  1005. Revision 1.45 1998/09/18 09:58:51 peter
  1006. * -s doesn't require the .o to be available, this allows compiling of
  1007. everything on other platforms (profiling the windows.pp loading ;)
  1008. Revision 1.44 1998/09/10 13:51:32 peter
  1009. * tp compiler also uses 'as' as asmprefix
  1010. Revision 1.43 1998/09/03 17:08:45 pierre
  1011. * better lines for stabs
  1012. (no scroll back to if before else part
  1013. no return to case line at jump outside case)
  1014. + source lines also if not in order
  1015. Revision 1.42 1998/09/03 11:24:00 peter
  1016. * moved more inputfile things from tscannerfile to tinputfile
  1017. * changed ifdef Sourceline to cs_asm_source
  1018. Revision 1.41 1998/08/26 15:35:30 peter
  1019. * fixed scannerfiles for macros
  1020. + $I %<environment>%
  1021. Revision 1.40 1998/08/26 10:08:48 peter
  1022. * fixed problem with libprefix at the wrong place
  1023. * fixed lib generation with smartlinking and no -CS used
  1024. Revision 1.39 1998/08/25 16:44:16 pierre
  1025. * openppu was true even if the object file is missing
  1026. this lead to trying to open a filename without extension
  1027. and prevented the 'make cycle' to work for win32
  1028. Revision 1.38 1998/08/19 10:06:12 peter
  1029. * fixed filenames and removedir which supports slash at the end
  1030. Revision 1.37 1998/08/18 20:52:19 peter
  1031. * renamed in_main to in_global which is more logical
  1032. Revision 1.36 1998/08/17 10:10:07 peter
  1033. - removed OLDPPU
  1034. Revision 1.35 1998/08/17 09:17:44 peter
  1035. * static/shared linking updates
  1036. Revision 1.34 1998/08/14 21:56:31 peter
  1037. * setting the outputfile using -o works now to create static libs
  1038. Revision 1.33 1998/08/11 14:09:08 peter
  1039. * fixed some messages and smaller msgtxt.inc
  1040. Revision 1.32 1998/08/10 14:49:58 peter
  1041. + localswitches, moduleswitches, globalswitches splitting
  1042. Revision 1.31 1998/07/14 14:46:48 peter
  1043. * released NEWINPUT
  1044. Revision 1.30 1998/07/07 11:19:55 peter
  1045. + NEWINPUT for a better inputfile and scanner object
  1046. Revision 1.29 1998/06/25 10:51:00 pierre
  1047. * removed a remaining ifndef NEWPPU
  1048. replaced by ifdef OLDPPU
  1049. * added uf_finalize to ppu unit
  1050. Revision 1.28 1998/06/25 08:48:12 florian
  1051. * first version of rtti support
  1052. Revision 1.27 1998/06/24 14:48:34 peter
  1053. * ifdef newppu -> ifndef oldppu
  1054. Revision 1.26 1998/06/17 14:36:19 peter
  1055. * forgot an $ifndef OLDPPU :(
  1056. Revision 1.25 1998/06/17 14:10:11 peter
  1057. * small os2 fixes
  1058. * fixed interdependent units with newppu (remake3 under linux works now)
  1059. Revision 1.24 1998/06/16 08:56:20 peter
  1060. + targetcpu
  1061. * cleaner pmodules for newppu
  1062. Revision 1.23 1998/06/15 14:44:36 daniel
  1063. * BP updates.
  1064. Revision 1.22 1998/06/14 18:25:41 peter
  1065. * small fix with crc in newppu
  1066. Revision 1.21 1998/06/13 00:10:05 peter
  1067. * working browser and newppu
  1068. * some small fixes against crashes which occured in bp7 (but not in
  1069. fpc?!)
  1070. Revision 1.20 1998/06/12 14:50:48 peter
  1071. * removed the tree dependency to types.pas
  1072. * long_fil.pas support (not fully tested yet)
  1073. Revision 1.19 1998/06/12 10:32:26 pierre
  1074. * column problem hopefully solved
  1075. + C vars declaration changed
  1076. Revision 1.18 1998/06/11 13:58:07 peter
  1077. * small fix to let newppu compile
  1078. Revision 1.17 1998/06/09 16:01:40 pierre
  1079. + added procedure directive parsing for procvars
  1080. (accepted are popstack cdecl and pascal)
  1081. + added C vars with the following syntax
  1082. var C calias 'true_c_name';(can be followed by external)
  1083. reason is that you must add the Cprefix
  1084. which is target dependent
  1085. Revision 1.16 1998/06/04 10:42:19 pierre
  1086. * small bug fix in load_ppu or openppu
  1087. Revision 1.15 1998/05/28 14:37:53 peter
  1088. * default programname is PROGRAM (like TP7) to avoid dup id's
  1089. Revision 1.14 1998/05/27 19:45:02 peter
  1090. * symtable.pas splitted into includefiles
  1091. * symtable adapted for $ifndef OLDPPU
  1092. Revision 1.13 1998/05/23 01:21:05 peter
  1093. + aktasmmode, aktoptprocessor, aktoutputformat
  1094. + smartlink per module $SMARTLINK-/+ (like MMX) and moved to aktswitches
  1095. + $LIBNAME to set the library name where the unit will be put in
  1096. * splitted cgi386 a bit (codeseg to large for bp7)
  1097. * nasm, tasm works again. nasm moved to ag386nsm.pas
  1098. Revision 1.12 1998/05/20 09:42:33 pierre
  1099. + UseTokenInfo now default
  1100. * unit in interface uses and implementation uses gives error now
  1101. * only one error for unknown symbol (uses lastsymknown boolean)
  1102. the problem came from the label code !
  1103. + first inlined procedures and function work
  1104. (warning there might be allowed cases were the result is still wrong !!)
  1105. * UseBrower updated gives a global list of all position of all used symbols
  1106. with switch -gb
  1107. Revision 1.11 1998/05/12 10:46:59 peter
  1108. * moved printstatus to verb_def
  1109. + V_Normal which is between V_Error and V_Warning and doesn't have a
  1110. prefix like error: warning: and is included in V_Default
  1111. * fixed some messages
  1112. * first time parameter scan is only for -v and -T
  1113. - removed old style messages
  1114. Revision 1.10 1998/05/11 13:07:53 peter
  1115. + $ifndef OLDPPU for the new ppuformat
  1116. + $define GDB not longer required
  1117. * removed all warnings and stripped some log comments
  1118. * no findfirst/findnext anymore to remove smartlink *.o files
  1119. Revision 1.9 1998/05/06 15:04:20 pierre
  1120. + when trying to find source files of a ppufile
  1121. check the includepathlist for included files
  1122. the main file must still be in the same directory
  1123. Revision 1.8 1998/05/04 17:54:25 peter
  1124. + smartlinking works (only case jumptable left todo)
  1125. * redesign of systems.pas to support assemblers and linkers
  1126. + Unitname is now also in the PPU-file, increased version to 14
  1127. Revision 1.7 1998/05/01 16:38:44 florian
  1128. * handling of private and protected fixed
  1129. + change_keywords_to_tp implemented to remove
  1130. keywords which aren't supported by tp
  1131. * break and continue are now symbols of the system unit
  1132. + widestring, longstring and ansistring type released
  1133. Revision 1.6 1998/05/01 07:43:53 florian
  1134. + basics for rtti implemented
  1135. + switch $m (generate rtti for published sections)
  1136. Revision 1.5 1998/04/30 15:59:40 pierre
  1137. * GDB works again better :
  1138. correct type info in one pass
  1139. + UseTokenInfo for better source position
  1140. * fixed one remaining bug in scanner for line counts
  1141. * several little fixes
  1142. Revision 1.4 1998/04/29 10:33:52 pierre
  1143. + added some code for ansistring (not complete nor working yet)
  1144. * corrected operator overloading
  1145. * corrected nasm output
  1146. + started inline procedures
  1147. + added starstarn : use ** for exponentiation (^ gave problems)
  1148. + started UseTokenInfo cond to get accurate positions
  1149. Revision 1.3 1998/04/27 23:10:28 peter
  1150. + new scanner
  1151. * $makelib -> if smartlink
  1152. * small filename fixes pmodule.setfilename
  1153. * moved import from files.pas -> import.pas
  1154. Revision 1.2 1998/04/21 10:16:47 peter
  1155. * patches from strasbourg
  1156. * objects is not used anymore in the fpc compiled version
  1157. }