files.pas 40 KB

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