123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503 |
- program FreePasResourcePreprocessor;
- {$ifdef win32}
- {$APPTYPE CONSOLE}
- {$endif}
- {$ifndef fpc}{$N+}{$endif}
- uses
- Comments,PasPrep,Expr,Classes
- {$ifndef win32}
- ,DOS;
- type
- str255=string[255];
- {$else}
- ;
- type
- str255=string[255];
- function SearchPath(path,name,ext:pchar;size:longint;buf:pchar;var x:pointer):longint;stdcall;
- external 'kernel32.dll' name 'SearchPathA';
- function FSearch(s,path:str255):Str255;
- var
- l:longint;
- procedure zeroterm(var s:str255);
- begin
- l:=length(s);
- move(s[1],s[0],l);
- s[l]:=#0;
- end;
- var
- buf:str255;
- aPtr:pointer;
- i:longint;
- begin
- zeroterm(path);
- zeroterm(s);
- i:=SearchPath(pchar(@path),pchar(@s),nil,255,pchar(@buf[1]),aPtr);
- if i<=255 then
- byte(buf[0]):=i
- else
- buf[0]:=#0;
- FSearch:=buf;
- end;
- {$endif}
- type
- pstring=^str255;
- PReplaceRec=^TReplaceRec;
- TReplaceRec=record
- next:PReplaceRec;
- CaseSentitive:longbool;
- oldvalue,newvalue:pstring;
- end;
- chars=array[1..2]of char;
- pchars=^chars;
- const
- Chain:PReplaceRec=nil;
- ChainHdr:PReplaceRec=nil;
- Chainlen:longint=0;
- var
- f:file;
- s:str255;
- sValue1, sValue2: String;
- size,nextpos:longint;
- buf:pchars;
- i:longint;
- AConstList: TStringList;
-
- function Entry(buf:pchars;Size,fromPos:longint;const sample:str255;casesent:longbool):longbool;
- var
- i:longint;
- c:char;
- begin
- Entry:=false;
- if(fromPos>1)and(buf^[pred(frompos)]>#32)then
- exit;
- if fromPos+length(sample)-1>=size then
- exit;
- if buf^[fromPos+length(sample)]>#32 then
- exit;
- Entry:=true;
- for i:=1 to length(sample)do
- begin
- if pred(fromPos+i)>size then
- begin
- Entry:=false;
- exit;
- end;
- c:=buf^[pred(fromPos+i)];
- if not casesent then
- c:=UpCase(c);
- if c<>sample[i]then
- begin
- Entry:=false;
- exit;
- end;
- end;
- end;
- function GetWord(buf:pchars;Size,fromPos:longint;var EndPos:longint):str255;
- var
- s:str255;
- i:longint;
- word_begin:longbool;
- begin
- s:='';
- i:=frompos;
- word_begin:=false;
- while i<size do
- begin
- if not word_begin then
- word_begin:=(buf^[i]>#32)and(buf^[i]<>';')and(buf^[i]<>'=');
- if word_begin then
- begin
- if not(buf^[i]in[#0..#32,';','='])then
- s:=s+buf^[i]
- else
- begin
- EndPos:=i;
- break;
- end;
- end;
- inc(i);
- end;
- GetWord:=s;
- end;
- procedure excludeComments(buf:pchars;size:longint);
- var
- comment:longbool;
- i:longint;
- begin
- comment:=false;
- for i:=1 to pred(size)do
- begin
- if(buf^[i]='/')and(buf^[succ(i)]='*')then
- comment:=true;
- if comment then
- begin
- if(buf^[i]='*')and(buf^[succ(i)]='/')then
- begin
- comment:=false;
- buf^[succ(i)]:=' ';
- end;
- buf^[i]:=' ';
- end;
- end;
- comment:=false;
- for i:=1 to pred(size)do
- begin
- if(buf^[i]='/')and(buf^[succ(i)]='/')then
- comment:=true;
- if comment then
- begin
- if buf^[i]in[#10,#13]then
- comment:=false;
- buf^[i]:=' ';
- end;
- end;
- end;
- function IsSwitch(const switch:str255):longbool;
- var
- i:longint;
- begin
- IsSwitch:=false;
- for i:=1 to ParamCount do
- if paramstr(i)='-'+switch then
- begin
- IsSwitch:=true;
- exit;
- end;
- end;
- function GetSwitch(const switch:str255):str255;
- var
- i:longint;
- begin
- GetSwitch:='';
- for i:=1 to paramcount do
- if paramstr(i)='-'+switch then
- GetSwitch:=paramstr(succ(i));
- end;
- type
- Tlanguage=(L_C,L_Pascal);
- function Language(s:str255):tLanguage;
- var
- s1,Lstr:str255;
- i,j:longint;
- found:longbool;
- type
- TLD=record
- x:string[3];
- l:tLanguage;
- end;
- const
- default:array[1..7]of TLD=(
- (x:'PAS';l:L_PASCAL),
- (x:'PP';l:L_PASCAL),
- (x:'P';l:L_PASCAL),
- (x:'DPR';l:L_PASCAL),
- (x:'IN?';l:L_PASCAL),
- (x:'C';l:L_C),
- (x:'H';l:L_C));
- begin
- Lstr:=GetSwitch('l');
- if lstr=''then
- Lstr:=GetSwitch('-language');
- for i:=1 to length(Lstr)do
- Lstr[i]:=UpCase(Lstr[i]);
- if Lstr='C'then
- begin
- Language:=L_C;
- exit;
- end
- else if(Lstr='PASCAL')or(Lstr='DELPHI')then
- begin
- Language:=L_PASCAL;
- exit;
- end
- else if (Lstr<>'')then
- writeln('Warning: unknown language ',Lstr);
- s1:='';
- for i:=length(s)downto 1 do
- begin
- if s[i]='.'then
- break;
- s1:=upcase(s[i])+s1;
- end;
- for i:=1 to 7 do
- begin
- found:=true;
- for j:=1 to length(s1)do
- if s1[j]<>default[i].x[j]then
- case default[i].x[j] of
- '?':
- ;
- else
- found:=false;
- end;
- if(found)and(s1<>'')then
- begin
- Language:=default[i].l;
- exit;
- end;
- end;
- Language:=L_PASCAL;
- end;
- function Up(const s:str255):str255;
- var
- n:str255;
- i:longint;
- begin
- n:=s;
- for i:=1 to length(s)do
- n[i]:=upcase(s[i]);
- Up:=n;
- end;
- procedure saveproc(const key,value:str255;CaseSent:longbool);{$ifndef fpc}far;{$endif}
- begin
- AConstList.Values[Up(key)]:=Up(Value);
- end;
- procedure do_C(buf:pchars;size:longint;proc:pointer);
- type
- Tpushfunc=procedure(const key,value:str255;CaseSent:longBool);
- var
- position:longint;
- charconst,stringconst:longbool;
- s,s0:str255;
- afunc:Tpushfunc absolute proc;
- procedure read(var s:str255;toEOL:longbool);
- var
- i:longint absolute position;
- function EndOfWord:longbool;
- begin
- if toEOL then
- EndOfWord:=buf^[i]in[#10,#13]
- else
- EndOfWord:=buf^[i]<=#32;
- end;
- begin
- s:='';
- if i>size then
- exit;
- while buf^[i]<=#32 do
- begin
- if i>size then
- exit;
- inc(i);
- end;
- repeat
- if i>size then
- exit;
- if not stringConst then
- if buf^[i]=''''then
- charconst:=not charconst;
- if not charConst then
- if buf^[i]='"'then
- stringconst:=not stringconst;
- if(not charconst)and(not stringconst)and EndOfWord then
- exit;
- if buf^[i]>#32 then
- s:=s+buf^[i];
- inc(i);
- until false;
- end;
- begin
- ExcludeComments(buf,size);
- position:=1;
- charconst:=false;
- stringconst:=false;
- repeat
- read(s,false);
- if Up(s)='#DEFINE' then
- begin
- read(s,false);
- read(s0,true);
- Tpushfunc(afunc)(s,s0,true);
- end;
- until position>=size;
- end;
- procedure expandname(var s:str255;path:str255);
- var
- astr:str255;
- begin
- astr:=fsearch(s,path);
- if astr<>''then
- s:={$ifndef Win32}FExpand{$endif}(astr);
- end;
- function do_include(name:str255):longbool;
- var
- bufinclude:pchars;
- finclude:file;
- sizeinclude:longint;
- s1:str255;
- procedure trim;
- begin
- delete(name,1,1);
- dec(name[0]);
- end;
- begin
- if (name[1]='"')and(name[length(name)]='"')then
- trim
- else if (name[1]='<')and(name[length(name)]='>')then
- begin
- trim;
- s1:=GetSwitch('p');
- if s1=''then
- s1:=GetSwitch('-path');
- expandname(name,s1);
- end;
- assign(finclude,name);
- reset(finclude,1);
- sizeinclude:=filesize(finclude);
- GetMem(bufinclude,sizeinclude);
- blockread(finclude,bufinclude^,sizeinclude);
- close(finclude);
- case Language(name)of
- L_C:
- do_C(bufinclude,sizeinclude,@saveProc);
- L_PASCAL:
- do_pascal(bufinclude,sizeinclude,@saveProc);
- end;
- FreeMem(bufinclude,sizeinclude);
- do_include:=true;
- end;
- function CheckRight(const s:str255;pos:longint):longbool;
- begin
- CheckRight:=true;
- if pos>length(s)then
- CheckRight:=false
- else
- CheckRight:=not(s[succ(pos)]in['a'..'z','A'..'Z','0'..'9','_']);
- end;
- function CheckLeft(const s:str255;pos:longint):longbool;
- begin
- CheckLeft:=true;
- if pos>1 then
- begin
- if pos>length(s)then
- CheckLeft:=false
- else
- CheckLeft:=not(s[pred(pos)]in['a'..'z','A'..'Z','0'..'9','_']);
- end;
- end;
- function Evaluate(Equation:String):String;
- var
- x:double;
- Err:integer;
- begin
- Eval(Equation,x,Err);
- if(Err=0)and(frac(x)=0)then
- str(x:1:0,Equation)
- else
- Equation:='';
- Evaluate:=Equation;
- end;
- type
- taccel=array[1..100]of pReplaceRec;
- var
- accel:^taccel;
- c:pReplaceRec;
- j,kk:longint;
- sss,sst:str255;
- bNoMore:Boolean;
- begin
- if(paramcount=0)or isSwitch('h')or isSwitch('-help')or((paramcount>1)and(GetSwitch('i')=''))then
- begin
- writeln('FPC CONSTANTS EXTRACTOR for resource scripts preprocessing');
- writeln('version 0.01');
- writeln('Usage: fprcp <file_name>');
- writeln('or:');
- writeln('fprcp -i <file_name> [-n] [-C] [-l PASCAL|C] [-p <include_path>]');
- writeln(' -C type C header instead preprocessed resource script');
- writeln(' -l set programming language for include files');
- writeln(' -p set path to include files');
- writeln(' -n disable support of pascal comments nesting');
- halt;
- end;
- if ParamCount=1 then
- assign(f,paramstr(1))
- else
- assign(f,GetSwitch('i'));
- reset(f,1);
- size:=filesize(f);
- getmem(buf,size);
- blockread(f,buf^,size);
- close(f);
- if isSwitch('n')then
- PasNesting:=false;
- if isSwitch('-disable-nested-pascal-comments')then
- PasNesting:=false;
- excludeComments(buf,size);
- AConstList:=TStringList.Create;
- //try
- AConstList.BeginUpdate;
- //try
- //include file
- for i:=1 to size do
- begin
- if entry(buf,size,i,'#include',true)then
- do_include(GetWord(buf,size,i+length('#include'),nextpos));
- end;
- //finally
- AConstList.EndUpdate; //end;
- //replace const-value if needed and evaluate
- For i:=0 to (AConstList.Count-1) do begin
- sValue1:=AConstList.ValueFromIndex[i];
- repeat
- sValue2:=AConstList.Values[sValue1];
- bNoMore:=Length(sValue2)=0;
- if (not bNoMore) then sValue1:=sValue2;
- until bNoMore;
- sValue2:=Evaluate(sValue1);
- if Length(sValue2)>0
- then AConstList.ValueFromIndex[i]:=Evaluate(sValue1);
- end;
-
- if isSwitch('C')or isSwitch('-Cheader')then begin
- for i:=0 to AConstList.Count-1
- do writeln('#define ',AConstList.Names[i],' ',AConstList.ValueFromIndex[i]);
- end else begin
- sss:='';
- i:=1;
- while i<=size do
- begin
- if buf^[i]<>#10 then
- sss:=sss+buf^[i]
- else
- begin
- while(sss<>'')and(sss[1]<=#32)do
- delete(sss,1,1);
- sst:=sss;
- for j:=1 to length(sst)do sst[j]:=upcase(sst[j]);
- if pos('#INCLUDE',sst)=0 then
- begin
- s:='';
- for kk:=1 to length(sss)do
- begin
- if sss[kk]>#32 then
- s:=s+sss[kk]
- else if s<>'' then
- begin
- sValue1:=AConstList.Values[Up(s)];
- if Length(sValue1)>0
- then write(sValue1,' ')
- else write(s,' ');
- s:='';
- end;
- end;
- writeln;
- sss:='';
- end
- else
- sss:='';
- end;
- inc(i);
- end;
- end;
- freemem(buf,size);
- //finally
- AConstList.Free; //end;
-
- end.
|