2
0

finput.pas 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736
  1. {
  2. $Id$
  3. Copyright (c) 1998-2002 by Florian Klaempfl
  4. This unit implements an extended file management
  5. This program is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2 of the License, or
  8. (at your option) any later version.
  9. This program is distributed in the hope that it will be useful,
  10. but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. GNU General Public License for more details.
  13. You should have received a copy of the GNU General Public License
  14. along with this program; if not, write to the Free Software
  15. Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  16. ****************************************************************************
  17. }
  18. unit finput;
  19. {$i fpcdefs.inc}
  20. interface
  21. uses
  22. cutils,cclasses;
  23. const
  24. InputFileBufSize=32*1024;
  25. linebufincrease=512;
  26. type
  27. tlongintarr = array[0..1000000] of longint;
  28. plongintarr = ^tlongintarr;
  29. tinputfile = class
  30. path,name : pstring; { path and filename }
  31. next : tinputfile; { next file for reading }
  32. is_macro,
  33. endoffile, { still bytes left to read }
  34. closed : boolean; { is the file closed }
  35. buf : pchar; { buffer }
  36. bufstart, { buffer start position in the file }
  37. bufsize, { amount of bytes in the buffer }
  38. maxbufsize : longint; { size in memory for the buffer }
  39. saveinputpointer : pchar; { save fields for scanner variables }
  40. savelastlinepos,
  41. saveline_no : longint;
  42. linebuf : plongintarr; { line buffer to retrieve lines }
  43. maxlinebuf : longint;
  44. ref_index : longint; { to handle the browser refs }
  45. ref_next : tinputfile;
  46. constructor create(const fn:string);
  47. destructor destroy;override;
  48. procedure setpos(l:longint);
  49. procedure seekbuf(fpos:longint);
  50. procedure readbuf;
  51. function open:boolean;
  52. procedure close;
  53. procedure tempclose;
  54. function tempopen:boolean;
  55. procedure setmacro(p:pchar;len:longint);
  56. procedure setline(line,linepos:longint);
  57. function getlinestr(l:longint):string;
  58. protected
  59. function fileopen(const filename: string): boolean; virtual;
  60. function fileseek(pos: longint): boolean; virtual;
  61. function fileread(var databuf; maxsize: longint): longint; virtual;
  62. function fileeof: boolean; virtual;
  63. function fileclose: boolean; virtual;
  64. end;
  65. tdosinputfile = class(tinputfile)
  66. protected
  67. function fileopen(const filename: string): boolean; override;
  68. function fileseek(pos: longint): boolean; override;
  69. function fileread(var databuf; maxsize: longint): longint; override;
  70. function fileeof: boolean; override;
  71. function fileclose: boolean; override;
  72. private
  73. f : file; { current file handle }
  74. end;
  75. tinputfilemanager = class
  76. files : tinputfile;
  77. last_ref_index : longint;
  78. cacheindex : longint;
  79. cacheinputfile : tinputfile;
  80. constructor create;
  81. destructor destroy;override;
  82. procedure register_file(f : tinputfile);
  83. procedure inverse_register_indexes;
  84. function get_file(l:longint) : tinputfile;
  85. function get_file_name(l :longint):string;
  86. function get_file_path(l :longint):string;
  87. end;
  88. {****************************************************************************
  89. TModuleBase
  90. ****************************************************************************}
  91. tmodulebase = class(TLinkedListItem)
  92. { index }
  93. unit_index : longint; { global counter for browser }
  94. { status }
  95. in_compile : boolean; { is it being compiled ?? }
  96. { sources }
  97. sourcefiles : tinputfilemanager;
  98. { paths and filenames }
  99. path, { path where the module is find/created }
  100. outputpath, { path where the .s / .o / exe are created }
  101. modulename, { name of the module in uppercase }
  102. realmodulename, { name of the module in the orignal case }
  103. objfilename, { fullname of the objectfile }
  104. newfilename, { fullname of the assemblerfile }
  105. ppufilename, { fullname of the ppufile }
  106. staticlibfilename, { fullname of the static libraryfile }
  107. sharedlibfilename, { fullname of the shared libraryfile }
  108. mapfilename, { fullname of the mapfile }
  109. exefilename, { fullname of the exefile }
  110. mainsource : pstring; { name of the main sourcefile }
  111. constructor create(const s:string);
  112. destructor destroy;override;
  113. procedure setfilename(const fn:string;allowoutput:boolean);
  114. function get_asmfilename : string;
  115. end;
  116. implementation
  117. uses
  118. {$ifdef Delphi}
  119. dmisc,
  120. {$else Delphi}
  121. dos,
  122. {$endif Delphi}
  123. {$ifdef HEAPTRC}
  124. fmodule,
  125. {$endif HEAPTRC}
  126. globals,systems
  127. ;
  128. {****************************************************************************
  129. TINPUTFILE
  130. ****************************************************************************}
  131. constructor tinputfile.create(const fn:string);
  132. var
  133. p:dirstr;
  134. n:namestr;
  135. e:extstr;
  136. begin
  137. FSplit(fn,p,n,e);
  138. name:=stringdup(n+e);
  139. path:=stringdup(p);
  140. next:=nil;
  141. { file info }
  142. is_macro:=false;
  143. endoffile:=false;
  144. closed:=true;
  145. buf:=nil;
  146. bufstart:=0;
  147. bufsize:=0;
  148. maxbufsize:=InputFileBufSize;
  149. { save fields }
  150. saveinputpointer:=nil;
  151. saveline_no:=0;
  152. savelastlinepos:=0;
  153. { indexing refs }
  154. ref_next:=nil;
  155. ref_index:=0;
  156. { line buffer }
  157. linebuf:=nil;
  158. maxlinebuf:=0;
  159. end;
  160. destructor tinputfile.destroy;
  161. begin
  162. if not closed then
  163. close;
  164. stringdispose(path);
  165. stringdispose(name);
  166. { free memory }
  167. if assigned(linebuf) then
  168. freemem(linebuf,maxlinebuf shl 2);
  169. end;
  170. procedure tinputfile.setpos(l:longint);
  171. begin
  172. bufstart:=l;
  173. end;
  174. procedure tinputfile.seekbuf(fpos:longint);
  175. begin
  176. if closed then
  177. exit;
  178. fileseek(fpos);
  179. bufstart:=fpos;
  180. bufsize:=0;
  181. end;
  182. procedure tinputfile.readbuf;
  183. begin
  184. if is_macro then
  185. endoffile:=true;
  186. if closed then
  187. exit;
  188. inc(bufstart,bufsize);
  189. bufsize:=fileread(buf^,maxbufsize-1);
  190. buf[bufsize]:=#0;
  191. endoffile:=fileeof;
  192. end;
  193. function tinputfile.open:boolean;
  194. begin
  195. open:=false;
  196. if not closed then
  197. Close;
  198. if not fileopen(path^+name^) then
  199. exit;
  200. { file }
  201. endoffile:=false;
  202. closed:=false;
  203. Getmem(buf,MaxBufsize);
  204. bufstart:=0;
  205. bufsize:=0;
  206. open:=true;
  207. end;
  208. procedure tinputfile.close;
  209. begin
  210. if is_macro then
  211. begin
  212. if assigned(buf) then
  213. begin
  214. Freemem(buf,maxbufsize);
  215. buf:=nil;
  216. end;
  217. closed:=true;
  218. exit;
  219. end;
  220. if not closed then
  221. begin
  222. fileclose;
  223. closed:=true;
  224. end;
  225. if assigned(buf) then
  226. begin
  227. Freemem(buf,maxbufsize);
  228. buf:=nil;
  229. end;
  230. bufstart:=0;
  231. end;
  232. procedure tinputfile.tempclose;
  233. begin
  234. if is_macro then
  235. exit;
  236. if not closed then
  237. begin
  238. fileclose;
  239. if assigned(buf) then
  240. begin
  241. Freemem(buf,maxbufsize);
  242. buf:=nil;
  243. end;
  244. closed:=true;
  245. end;
  246. end;
  247. function tinputfile.tempopen:boolean;
  248. begin
  249. tempopen:=false;
  250. if is_macro then
  251. begin
  252. { seek buffer postion to bufstart }
  253. if bufstart>0 then
  254. begin
  255. move(buf[bufstart],buf[0],bufsize-bufstart+1);
  256. bufstart:=0;
  257. end;
  258. tempopen:=true;
  259. exit;
  260. end;
  261. if not closed then
  262. exit;
  263. if not fileopen(path^+name^) then
  264. exit;
  265. closed:=false;
  266. { get new mem }
  267. Getmem(buf,maxbufsize);
  268. { restore state }
  269. fileseek(BufStart);
  270. bufsize:=0;
  271. readbuf;
  272. tempopen:=true;
  273. end;
  274. procedure tinputfile.setmacro(p:pchar;len:longint);
  275. begin
  276. { create new buffer }
  277. getmem(buf,len+1);
  278. move(p^,buf^,len);
  279. buf[len]:=#0;
  280. { reset }
  281. bufstart:=0;
  282. bufsize:=len;
  283. maxbufsize:=len+1;
  284. is_macro:=true;
  285. endoffile:=true;
  286. closed:=true;
  287. end;
  288. procedure tinputfile.setline(line,linepos:longint);
  289. var
  290. oldlinebuf : plongintarr;
  291. begin
  292. if line<1 then
  293. exit;
  294. while (line>=maxlinebuf) do
  295. begin
  296. oldlinebuf:=linebuf;
  297. { create new linebuf and move old info }
  298. getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
  299. if assigned(oldlinebuf) then
  300. begin
  301. move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
  302. freemem(oldlinebuf,maxlinebuf shl 2);
  303. end;
  304. fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
  305. inc(maxlinebuf,linebufincrease);
  306. end;
  307. linebuf^[line]:=linepos;
  308. end;
  309. function tinputfile.getlinestr(l:longint):string;
  310. var
  311. c : char;
  312. i,
  313. fpos : longint;
  314. p : pchar;
  315. begin
  316. getlinestr:='';
  317. if l<maxlinebuf then
  318. begin
  319. fpos:=linebuf^[l];
  320. { fpos is set negativ if the line was already written }
  321. { but we still know the correct value }
  322. if fpos<0 then
  323. fpos:=-fpos+1;
  324. if closed then
  325. open;
  326. { in current buf ? }
  327. if (fpos<bufstart) or (fpos>bufstart+bufsize) then
  328. begin
  329. seekbuf(fpos);
  330. readbuf;
  331. end;
  332. { the begin is in the buf now simply read until #13,#10 }
  333. i:=0;
  334. p:=@buf[fpos-bufstart];
  335. repeat
  336. c:=p^;
  337. if c=#0 then
  338. begin
  339. if endoffile then
  340. break;
  341. readbuf;
  342. p:=buf;
  343. c:=p^;
  344. end;
  345. if c in [#10,#13] then
  346. break;
  347. inc(i);
  348. getlinestr[i]:=c;
  349. inc(longint(p));
  350. until (i=255);
  351. getlinestr[0]:=chr(i);
  352. end;
  353. end;
  354. function tinputfile.fileopen(const filename: string): boolean;
  355. begin
  356. abstract;
  357. fileopen:=false;
  358. end;
  359. function tinputfile.fileseek(pos: longint): boolean;
  360. begin
  361. abstract;
  362. fileseek:=false;
  363. end;
  364. function tinputfile.fileread(var databuf; maxsize: longint): longint;
  365. begin
  366. abstract;
  367. fileread:=0;
  368. end;
  369. function tinputfile.fileeof: boolean;
  370. begin
  371. abstract;
  372. fileeof:=false;
  373. end;
  374. function tinputfile.fileclose: boolean;
  375. begin
  376. abstract;
  377. fileclose:=false;
  378. end;
  379. {****************************************************************************
  380. TDOSINPUTFILE
  381. ****************************************************************************}
  382. function tdosinputfile.fileopen(const filename: string): boolean;
  383. var
  384. ofm : byte;
  385. begin
  386. ofm:=filemode;
  387. filemode:=0;
  388. Assign(f,filename);
  389. {$I-}
  390. reset(f,1);
  391. {$I+}
  392. filemode:=ofm;
  393. fileopen:=(ioresult=0);
  394. end;
  395. function tdosinputfile.fileseek(pos: longint): boolean;
  396. begin
  397. {$I-}
  398. seek(f,Pos);
  399. {$I+}
  400. fileseek:=(ioresult=0);
  401. end;
  402. function tdosinputfile.fileread(var databuf; maxsize: longint): longint;
  403. var
  404. w : longint;
  405. begin
  406. blockread(f,databuf,maxsize,w);
  407. fileread:=w;
  408. end;
  409. function tdosinputfile.fileeof: boolean;
  410. begin
  411. fileeof:=eof(f);
  412. end;
  413. function tdosinputfile.fileclose: boolean;
  414. begin
  415. {$I-}
  416. system.close(f);
  417. {$I+}
  418. fileclose:=(ioresult=0);
  419. end;
  420. {****************************************************************************
  421. Tinputfilemanager
  422. ****************************************************************************}
  423. constructor tinputfilemanager.create;
  424. begin
  425. files:=nil;
  426. last_ref_index:=0;
  427. cacheindex:=0;
  428. cacheinputfile:=nil;
  429. end;
  430. destructor tinputfilemanager.destroy;
  431. var
  432. hp : tinputfile;
  433. begin
  434. hp:=files;
  435. while assigned(hp) do
  436. begin
  437. files:=files.ref_next;
  438. hp.free;
  439. hp:=files;
  440. end;
  441. last_ref_index:=0;
  442. end;
  443. procedure tinputfilemanager.register_file(f : tinputfile);
  444. begin
  445. { don't register macro's }
  446. if f.is_macro then
  447. exit;
  448. inc(last_ref_index);
  449. f.ref_next:=files;
  450. f.ref_index:=last_ref_index;
  451. files:=f;
  452. { update cache }
  453. cacheindex:=last_ref_index;
  454. cacheinputfile:=f;
  455. {$ifdef HEAPTRC}
  456. writeln(stderr,f.name^,' index ',current_module.unit_index*100000+f.ref_index);
  457. {$endif HEAPTRC}
  458. end;
  459. { this procedure is necessary after loading the
  460. sources files from a PPU file PM }
  461. procedure tinputfilemanager.inverse_register_indexes;
  462. var
  463. f : tinputfile;
  464. begin
  465. f:=files;
  466. while assigned(f) do
  467. begin
  468. f.ref_index:=last_ref_index-f.ref_index+1;
  469. f:=f.ref_next;
  470. end;
  471. { reset cache }
  472. cacheindex:=0;
  473. cacheinputfile:=nil;
  474. end;
  475. function tinputfilemanager.get_file(l :longint) : tinputfile;
  476. var
  477. ff : tinputfile;
  478. begin
  479. { check cache }
  480. if (l=cacheindex) and assigned(cacheinputfile) then
  481. begin
  482. get_file:=cacheinputfile;
  483. exit;
  484. end;
  485. ff:=files;
  486. while assigned(ff) and (ff.ref_index<>l) do
  487. ff:=ff.ref_next;
  488. get_file:=ff;
  489. end;
  490. function tinputfilemanager.get_file_name(l :longint):string;
  491. var
  492. hp : tinputfile;
  493. begin
  494. hp:=get_file(l);
  495. if assigned(hp) then
  496. get_file_name:=hp.name^
  497. else
  498. get_file_name:='';
  499. end;
  500. function tinputfilemanager.get_file_path(l :longint):string;
  501. var
  502. hp : tinputfile;
  503. begin
  504. hp:=get_file(l);
  505. if assigned(hp) then
  506. get_file_path:=hp.path^
  507. else
  508. get_file_path:='';
  509. end;
  510. {****************************************************************************
  511. TModuleBase
  512. ****************************************************************************}
  513. procedure tmodulebase.setfilename(const fn:string;allowoutput:boolean);
  514. var
  515. p : dirstr;
  516. n : NameStr;
  517. e : ExtStr;
  518. begin
  519. stringdispose(objfilename);
  520. stringdispose(newfilename);
  521. stringdispose(ppufilename);
  522. stringdispose(staticlibfilename);
  523. stringdispose(sharedlibfilename);
  524. stringdispose(mapfilename);
  525. stringdispose(exefilename);
  526. stringdispose(outputpath);
  527. stringdispose(path);
  528. { Create names }
  529. fsplit(fn,p,n,e);
  530. n:=FixFileName(n);
  531. { set path }
  532. path:=stringdup(FixPath(p,false));
  533. { obj,asm,ppu names }
  534. p:=path^;
  535. if AllowOutput then
  536. begin
  537. if (OutputUnitDir<>'') then
  538. p:=OutputUnitDir
  539. else
  540. if (OutputExeDir<>'') then
  541. p:=OutputExeDir;
  542. end;
  543. outputpath:=stringdup(p);
  544. newfilename := stringdup(n);
  545. objfilename:=stringdup(p+n+target_info.objext);
  546. ppufilename:=stringdup(p+n+target_info.unitext);
  547. { lib and exe could be loaded with a file specified with -o }
  548. if AllowOutput and (OutputFile<>'') and (compile_level=1) then
  549. n:=OutputFile;
  550. staticlibfilename:=stringdup(p+target_info.staticlibprefix+n+target_info.staticlibext);
  551. if target_info.system in [system_i386_WIN32,system_i386_wdosx] then
  552. sharedlibfilename:=stringdup(p+n+target_info.sharedlibext)
  553. else
  554. sharedlibfilename:=stringdup(p+target_info.sharedlibprefix+n+target_info.sharedlibext);
  555. { output dir of exe can be specified separatly }
  556. if AllowOutput and (OutputExeDir<>'') then
  557. p:=OutputExeDir
  558. else
  559. p:=path^;
  560. exefilename:=stringdup(p+n+target_info.exeext);
  561. mapfilename:=stringdup(p+n+'.map');
  562. end;
  563. constructor tmodulebase.create(const s:string);
  564. begin
  565. modulename:=stringdup(Upper(s));
  566. realmodulename:=stringdup(s);
  567. mainsource:=nil;
  568. ppufilename:=nil;
  569. objfilename:=nil;
  570. newfilename:=nil;
  571. staticlibfilename:=nil;
  572. sharedlibfilename:=nil;
  573. exefilename:=nil;
  574. mapfilename:=nil;
  575. outputpath:=nil;
  576. path:=nil;
  577. { status }
  578. in_compile:=false;
  579. { unit index }
  580. inc(global_unit_count);
  581. unit_index:=global_unit_count;
  582. { sources }
  583. sourcefiles:=TInputFileManager.Create;
  584. end;
  585. function tmodulebase.get_asmfilename : string;
  586. begin
  587. get_asmfilename:=outputpath^+newfilename^+target_info.asmext;
  588. end;
  589. destructor tmodulebase.destroy;
  590. begin
  591. if assigned(sourcefiles) then
  592. sourcefiles.free;
  593. sourcefiles:=nil;
  594. stringdispose(objfilename);
  595. stringdispose(newfilename);
  596. stringdispose(ppufilename);
  597. stringdispose(staticlibfilename);
  598. stringdispose(sharedlibfilename);
  599. stringdispose(exefilename);
  600. stringdispose(mapfilename);
  601. stringdispose(outputpath);
  602. stringdispose(path);
  603. stringdispose(modulename);
  604. stringdispose(realmodulename);
  605. stringdispose(mainsource);
  606. inherited destroy;
  607. end;
  608. end.
  609. {
  610. $Log$
  611. Revision 1.18 2002-08-11 13:24:11 peter
  612. * saving of asmsymbols in ppu supported
  613. * asmsymbollist global is removed and moved into a new class
  614. tasmlibrarydata that will hold the info of a .a file which
  615. corresponds with a single module. Added librarydata to tmodule
  616. to keep the library info stored for the module. In the future the
  617. objectfiles will also be stored to the tasmlibrarydata class
  618. * all getlabel/newasmsymbol and friends are moved to the new class
  619. Revision 1.17 2002/07/26 21:15:37 florian
  620. * rewrote the system handling
  621. Revision 1.16 2002/07/01 18:46:22 peter
  622. * internal linker
  623. * reorganized aasm layer
  624. Revision 1.15 2002/05/18 13:34:07 peter
  625. * readded missing revisions
  626. Revision 1.14 2002/05/16 19:46:36 carl
  627. + defines.inc -> fpcdefs.inc to avoid conflicts if compiling by hand
  628. + try to fix temp allocation (still in ifdef)
  629. + generic constructor calls
  630. + start of tassembler / tmodulebase class cleanup
  631. Revision 1.13 2002/05/14 19:34:41 peter
  632. * removed old logs and updated copyright year
  633. Revision 1.12 2002/04/04 18:34:00 carl
  634. + added wdosx support (patch from Pavel)
  635. }