123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723 |
- {
- Copyright (c) 1998-2002 by Florian Klaempfl
- This unit implements an extended file management
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
- ****************************************************************************
- }
- unit finput;
- {$i fpcdefs.inc}
- interface
- uses
- cutils,cclasses;
- const
- InputFileBufSize=32*1024;
- linebufincrease=512;
- type
- tlongintarr = array[0..1000000] of longint;
- plongintarr = ^tlongintarr;
- tinputfile = class
- path,name : pshortstring; { path and filename }
- next : tinputfile; { next file for reading }
- is_macro,
- endoffile, { still bytes left to read }
- closed : boolean; { is the file closed }
- buf : pchar; { buffer }
- bufstart, { buffer start position in the file }
- bufsize, { amount of bytes in the buffer }
- maxbufsize : longint; { size in memory for the buffer }
- saveinputpointer : pchar; { save fields for scanner variables }
- savelastlinepos,
- saveline_no : longint;
- linebuf : plongintarr; { line buffer to retrieve lines }
- maxlinebuf : longint;
- ref_index : longint;
- ref_next : tinputfile;
- constructor create(const fn:string);
- destructor destroy;override;
- procedure setpos(l:longint);
- procedure seekbuf(fpos:longint);
- procedure readbuf;
- function open:boolean;
- procedure close;
- procedure tempclose;
- function tempopen:boolean;
- procedure setmacro(p:pchar;len:longint);
- procedure setline(line,linepos:longint);
- function getlinestr(l:longint):string;
- function getfiletime:longint;
- protected
- filetime : longint;
- function fileopen(const filename: string): boolean; virtual; abstract;
- function fileseek(pos: longint): boolean; virtual; abstract;
- function fileread(var databuf; maxsize: longint): longint; virtual; abstract;
- function fileeof: boolean; virtual; abstract;
- function fileclose: boolean; virtual; abstract;
- procedure filegettime; virtual; abstract;
- end;
- tdosinputfile = class(tinputfile)
- protected
- function fileopen(const filename: string): boolean; override;
- function fileseek(pos: longint): boolean; override;
- function fileread(var databuf; maxsize: longint): longint; override;
- function fileeof: boolean; override;
- function fileclose: boolean; override;
- procedure filegettime; override;
- private
- f : file; { current file handle }
- end;
- tinputfilemanager = class
- files : tinputfile;
- last_ref_index : longint;
- cacheindex : longint;
- cacheinputfile : tinputfile;
- constructor create;
- destructor destroy;override;
- procedure register_file(f : tinputfile);
- function get_file(l:longint) : tinputfile;
- function get_file_name(l :longint):string;
- function get_file_path(l :longint):string;
- end;
- {****************************************************************************
- TModuleBase
- ****************************************************************************}
- type
- tmodulestate = (ms_unknown,
- ms_registered,
- ms_load,ms_compile,
- ms_second_load,ms_second_compile,
- ms_compiled
- );
- const
- ModuleStateStr : array[TModuleState] of string[20] = (
- 'Unknown',
- 'Registered',
- 'Load','Compile',
- 'Second_Load','Second_Compile',
- 'Compiled'
- );
- type
- tmodulebase = class(TLinkedListItem)
- { index }
- unit_index : longint; { global counter for browser }
- { status }
- state : tmodulestate;
- { sources }
- sourcefiles : tinputfilemanager;
- { paths and filenames }
- paramallowoutput : boolean; { original allowoutput parameter }
- paramfn, { original filename }
- path, { path where the module is find/created }
- outputpath, { path where the .s / .o / exe are created }
- modulename, { name of the module in uppercase }
- realmodulename, { name of the module in the orignal case }
- objfilename, { fullname of the objectfile }
- asmfilename, { fullname of the assemblerfile }
- ppufilename, { fullname of the ppufile }
- importlibfilename, { fullname of the import libraryfile }
- staticlibfilename, { fullname of the static libraryfile }
- sharedlibfilename, { fullname of the shared libraryfile }
- mapfilename, { fullname of the mapfile }
- exefilename, { fullname of the exefile }
- mainsource : pshortstring; { name of the main sourcefile }
- constructor create(const s:string);
- destructor destroy;override;
- procedure setfilename(const fn:string;allowoutput:boolean);
- end;
- Function GetNamedFileTime (Const F : String) : Longint;
- implementation
- uses
- SysUtils,
- GlobType,Comphook,
- {$ifdef heaptrc}
- fmodule,
- ppheap,
- {$endif heaptrc}
- CFileUtils,
- Globals,Systems
- ;
- {****************************************************************************
- Utils
- ****************************************************************************}
- Function GetNamedFileTime (Const F : String) : Longint;
- begin
- GetNamedFileTime:=do_getnamedfiletime(F);
- end;
- {****************************************************************************
- TINPUTFILE
- ****************************************************************************}
- constructor tinputfile.create(const fn:string);
- begin
- name:=stringdup(ExtractFileName(fn));
- path:=stringdup(ExtractFilePath(fn));
- next:=nil;
- filetime:=-1;
- { file info }
- is_macro:=false;
- endoffile:=false;
- closed:=true;
- buf:=nil;
- bufstart:=0;
- bufsize:=0;
- maxbufsize:=InputFileBufSize;
- { save fields }
- saveinputpointer:=nil;
- saveline_no:=0;
- savelastlinepos:=0;
- { indexing refs }
- ref_next:=nil;
- ref_index:=0;
- { line buffer }
- linebuf:=nil;
- maxlinebuf:=0;
- end;
- destructor tinputfile.destroy;
- begin
- if not closed then
- close;
- stringdispose(path);
- stringdispose(name);
- { free memory }
- if assigned(linebuf) then
- freemem(linebuf,maxlinebuf shl 2);
- end;
- procedure tinputfile.setpos(l:longint);
- begin
- bufstart:=l;
- end;
- procedure tinputfile.seekbuf(fpos:longint);
- begin
- if closed then
- exit;
- fileseek(fpos);
- bufstart:=fpos;
- bufsize:=0;
- end;
- procedure tinputfile.readbuf;
- begin
- if is_macro then
- endoffile:=true;
- if closed then
- exit;
- inc(bufstart,bufsize);
- bufsize:=fileread(buf^,maxbufsize-1);
- buf[bufsize]:=#0;
- endoffile:=fileeof;
- end;
- function tinputfile.open:boolean;
- begin
- open:=false;
- if not closed then
- Close;
- if not fileopen(path^+name^) then
- exit;
- { file }
- endoffile:=false;
- closed:=false;
- Getmem(buf,MaxBufsize);
- bufstart:=0;
- bufsize:=0;
- open:=true;
- end;
- procedure tinputfile.close;
- begin
- if is_macro then
- begin
- if assigned(buf) then
- begin
- Freemem(buf,maxbufsize);
- buf:=nil;
- end;
- closed:=true;
- exit;
- end;
- if not closed then
- begin
- fileclose;
- closed:=true;
- end;
- if assigned(buf) then
- begin
- Freemem(buf,maxbufsize);
- buf:=nil;
- end;
- bufstart:=0;
- end;
- procedure tinputfile.tempclose;
- begin
- if is_macro then
- exit;
- if not closed then
- begin
- fileclose;
- if assigned(buf) then
- begin
- Freemem(buf,maxbufsize);
- buf:=nil;
- end;
- closed:=true;
- end;
- end;
- function tinputfile.tempopen:boolean;
- begin
- tempopen:=false;
- if is_macro then
- begin
- { seek buffer postion to bufstart }
- if bufstart>0 then
- begin
- move(buf[bufstart],buf[0],bufsize-bufstart+1);
- bufstart:=0;
- end;
- tempopen:=true;
- exit;
- end;
- if not closed then
- exit;
- if not fileopen(path^+name^) then
- exit;
- closed:=false;
- { get new mem }
- Getmem(buf,maxbufsize);
- { restore state }
- fileseek(BufStart);
- bufsize:=0;
- readbuf;
- tempopen:=true;
- end;
- procedure tinputfile.setmacro(p:pchar;len:longint);
- begin
- { create new buffer }
- getmem(buf,len+1);
- move(p^,buf^,len);
- buf[len]:=#0;
- { reset }
- bufstart:=0;
- bufsize:=len;
- maxbufsize:=len+1;
- is_macro:=true;
- endoffile:=true;
- closed:=true;
- end;
- procedure tinputfile.setline(line,linepos:longint);
- var
- oldlinebuf : plongintarr;
- begin
- if line<1 then
- exit;
- while (line>=maxlinebuf) do
- begin
- oldlinebuf:=linebuf;
- { create new linebuf and move old info }
- getmem(linebuf,(maxlinebuf+linebufincrease) shl 2);
- if assigned(oldlinebuf) then
- begin
- move(oldlinebuf^,linebuf^,maxlinebuf shl 2);
- freemem(oldlinebuf,maxlinebuf shl 2);
- end;
- fillchar(linebuf^[maxlinebuf],linebufincrease shl 2,0);
- inc(maxlinebuf,linebufincrease);
- end;
- linebuf^[line]:=linepos;
- end;
- function tinputfile.getlinestr(l:longint):string;
- var
- c : char;
- i,
- fpos : longint;
- p : pchar;
- begin
- getlinestr:='';
- if l<maxlinebuf then
- begin
- fpos:=linebuf^[l];
- { fpos is set negativ if the line was already written }
- { but we still know the correct value }
- if fpos<0 then
- fpos:=-fpos+1;
- if closed then
- open;
- { in current buf ? }
- if (fpos<bufstart) or (fpos>bufstart+bufsize) then
- begin
- seekbuf(fpos);
- readbuf;
- end;
- { the begin is in the buf now simply read until #13,#10 }
- i:=0;
- p:=@buf[fpos-bufstart];
- repeat
- c:=p^;
- if c=#0 then
- begin
- if endoffile then
- break;
- readbuf;
- p:=buf;
- c:=p^;
- end;
- if c in [#10,#13] then
- break;
- inc(i);
- getlinestr[i]:=c;
- inc(p);
- until (i=255);
- getlinestr[0]:=chr(i);
- end;
- end;
- function tinputfile.getfiletime:longint;
- begin
- if filetime=-1 then
- filegettime;
- getfiletime:=filetime;
- end;
- {****************************************************************************
- TDOSINPUTFILE
- ****************************************************************************}
- function tdosinputfile.fileopen(const filename: string): boolean;
- var
- ofm : byte;
- begin
- { Check if file exists, this will also check if it is
- a real file and not a directory }
- if not fileexists(filename,false) then
- begin
- result:=false;
- exit;
- end;
- { Open file }
- ofm:=filemode;
- filemode:=0;
- Assign(f,filename);
- {$I-}
- reset(f,1);
- {$I+}
- filemode:=ofm;
- fileopen:=(ioresult=0);
- end;
- function tdosinputfile.fileseek(pos: longint): boolean;
- begin
- {$I-}
- seek(f,Pos);
- {$I+}
- fileseek:=(ioresult=0);
- end;
- function tdosinputfile.fileread(var databuf; maxsize: longint): longint;
- var
- w : longint;
- begin
- blockread(f,databuf,maxsize,w);
- fileread:=w;
- end;
- function tdosinputfile.fileeof: boolean;
- begin
- fileeof:=eof(f);
- end;
- function tdosinputfile.fileclose: boolean;
- begin
- {$I-}
- system.close(f);
- {$I+}
- fileclose:=(ioresult=0);
- end;
- procedure tdosinputfile.filegettime;
- begin
- filetime:=getnamedfiletime(path^+name^);
- end;
- {****************************************************************************
- Tinputfilemanager
- ****************************************************************************}
- constructor tinputfilemanager.create;
- begin
- files:=nil;
- last_ref_index:=0;
- cacheindex:=0;
- cacheinputfile:=nil;
- end;
- destructor tinputfilemanager.destroy;
- var
- hp : tinputfile;
- begin
- hp:=files;
- while assigned(hp) do
- begin
- files:=files.ref_next;
- hp.free;
- hp:=files;
- end;
- last_ref_index:=0;
- end;
- procedure tinputfilemanager.register_file(f : tinputfile);
- begin
- { don't register macro's }
- if f.is_macro then
- exit;
- inc(last_ref_index);
- f.ref_next:=files;
- f.ref_index:=last_ref_index;
- files:=f;
- { update cache }
- cacheindex:=last_ref_index;
- cacheinputfile:=f;
- {$ifdef heaptrc}
- ppheap_register_file(f.name^,current_module.unit_index*100000+f.ref_index);
- {$endif heaptrc}
- end;
- function tinputfilemanager.get_file(l :longint) : tinputfile;
- var
- ff : tinputfile;
- begin
- { check cache }
- if (l=cacheindex) and assigned(cacheinputfile) then
- begin
- get_file:=cacheinputfile;
- exit;
- end;
- ff:=files;
- while assigned(ff) and (ff.ref_index<>l) do
- ff:=ff.ref_next;
- if assigned(ff) then
- begin
- cacheindex:=ff.ref_index;
- cacheinputfile:=ff;
- end;
- get_file:=ff;
- end;
- function tinputfilemanager.get_file_name(l :longint):string;
- var
- hp : tinputfile;
- begin
- hp:=get_file(l);
- if assigned(hp) then
- get_file_name:=hp.name^
- else
- get_file_name:='';
- end;
- function tinputfilemanager.get_file_path(l :longint):string;
- var
- hp : tinputfile;
- begin
- hp:=get_file(l);
- if assigned(hp) then
- get_file_path:=hp.path^
- else
- get_file_path:='';
- end;
- {****************************************************************************
- TModuleBase
- ****************************************************************************}
- procedure tmodulebase.setfilename(const fn:string;allowoutput:boolean);
- var
- p,n,
- prefix,
- suffix : string;
- begin
- stringdispose(objfilename);
- stringdispose(asmfilename);
- stringdispose(ppufilename);
- stringdispose(importlibfilename);
- stringdispose(staticlibfilename);
- stringdispose(sharedlibfilename);
- stringdispose(mapfilename);
- stringdispose(exefilename);
- stringdispose(outputpath);
- stringdispose(path);
- stringdispose(paramfn);
- { Create names }
- paramfn := stringdup(fn);
- paramallowoutput := allowoutput;
- p := FixPath(ExtractFilePath(fn),false);
- n := FixFileName(ChangeFileExt(ExtractFileName(fn),''));
- { set path }
- path:=stringdup(p);
- { obj,asm,ppu names }
- if AllowOutput then
- begin
- if (OutputUnitDir<>'') then
- p:=OutputUnitDir
- else
- if (OutputExeDir<>'') then
- p:=OutputExeDir;
- end;
- outputpath:=stringdup(p);
- asmfilename:=stringdup(p+n+target_info.asmext);
- objfilename:=stringdup(p+n+target_info.objext);
- ppufilename:=stringdup(p+n+target_info.unitext);
- importlibfilename:=stringdup(p+target_info.staticClibprefix+'imp'+n+target_info.staticlibext);
- staticlibfilename:=stringdup(p+target_info.staticlibprefix+n+target_info.staticlibext);
- { output dir of exe can be specified separatly }
- if AllowOutput and (OutputExeDir<>'') then
- p:=OutputExeDir
- else
- p:=path^;
- { lib and exe could be loaded with a file specified with -o }
- if AllowOutput and
- (compile_level=1) and
- (OutputFileName<>'')then
- begin
- exefilename:=stringdup(p+OutputFileName);
- sharedlibfilename:=stringdup(p+OutputFileName);
- end
- else
- begin
- exefilename:=stringdup(p+n+target_info.exeext);
- if Assigned(OutputPrefix) then
- prefix := OutputPrefix^
- else
- prefix := target_info.sharedlibprefix;
- if Assigned(OutputSuffix) then
- suffix := OutputSuffix^
- else
- suffix := '';
- sharedlibfilename:=stringdup(p+prefix+n+suffix+target_info.sharedlibext);
- end;
- mapfilename:=stringdup(p+n+'.map');
- end;
- constructor tmodulebase.create(const s:string);
- begin
- modulename:=stringdup(Upper(s));
- realmodulename:=stringdup(s);
- mainsource:=nil;
- ppufilename:=nil;
- objfilename:=nil;
- asmfilename:=nil;
- importlibfilename:=nil;
- staticlibfilename:=nil;
- sharedlibfilename:=nil;
- exefilename:=nil;
- mapfilename:=nil;
- outputpath:=nil;
- paramfn:=nil;
- path:=nil;
- { status }
- state:=ms_registered;
- { unit index }
- inc(global_unit_count);
- unit_index:=global_unit_count;
- { sources }
- sourcefiles:=TInputFileManager.Create;
- end;
- destructor tmodulebase.destroy;
- begin
- if assigned(sourcefiles) then
- sourcefiles.free;
- sourcefiles:=nil;
- stringdispose(objfilename);
- stringdispose(asmfilename);
- stringdispose(ppufilename);
- stringdispose(importlibfilename);
- stringdispose(staticlibfilename);
- stringdispose(sharedlibfilename);
- stringdispose(exefilename);
- stringdispose(mapfilename);
- stringdispose(outputpath);
- stringdispose(path);
- stringdispose(modulename);
- stringdispose(realmodulename);
- stringdispose(mainsource);
- stringdispose(paramfn);
- inherited destroy;
- end;
- end.
|