files.pas 41 KB

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