fpc/compiler/cresstr.pas
1999-07-24 16:22:10 +00:00

243 lines
6.8 KiB
ObjectPascal

{
$Id$
Copyright (c) 1999 by the Free Pascal development team
Handles resourcestrings
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 cresstr;
interface
procedure insertresourcestrings;
procedure registerresourcestring(Const name : string;p : pchar;len,hash : longint);
function calc_resstring_hashvalue(p : pchar;len : longint) : longint;
Procedure WriteResourceFile(FileName : String);
implementation
uses
globals,aasm,verbose,files;
Type
PResourcestring = ^TResourceString;
TResourceString = record
Name : String;
Value : Pchar;
Len,hash : longint;
Next : PResourcestring;
end;
const
{ we can use a static constant because we compile a program only once }
{ per compiler call }
resstrcount : longint = 0;
resourcefilename = 'resource.rst';
Var
ResourceListRoot : PResourceString;
{ calcs the hash value for a give resourcestring, len is }
{ necessary because the resourcestring can contain #0 }
function calc_resstring_hashvalue(p : pchar;len : longint) : longint;
Var hash,g,I : longint;
begin
hash:=len;
For I:=0 to Len-1 do // 0 terminated
begin
hash:=hash shl 4;
inc(Hash,Ord(p[i]));
g:=hash and ($f shl 28);
if g<>0 then
begin
hash:=hash xor (g shr 24);
hash:=hash xor g;
end;
end;
If Hash=0 then
Calc_resstring_hashvalue:=Not(0)
else
calc_resstring_hashvalue:=Hash;
end;
procedure insertresourcestrings;
begin
if not(assigned(resourcestringlist)) then
resourcestringlist:=new(paasmoutput,init);
resourcestringlist^.insert(new(pai_const,init_32bit(resstrcount)));
resourcestringlist^.insert(new(pai_symbol,initname_global('RESOURCESTRINGLIST')));
end;
Procedure AppendToResourceList(const name : string;p : pchar;len,hash : longint);
Var R : PResourceString;
begin
inc(resstrcount);
New(R);
R^.Name:=NAme;
r^.Len:=Len;
R^.Hash:=hash;
GetMem(R^.Value,Len);
Move(P^,R^.Value^,Len);
R^.Next:=ResourceListRoot;
ResourceListRoot:=R;
end;
procedure registerresourcestring(const name : string;p : pchar;len,hash : longint);
var
l1 : pasmlabel;
s : pchar;
begin
{ we don't need to generate consts in units }
if (main_module^.is_unit) then
exit;
if not(assigned(resourcestringlist)) then
resourcestringlist:=new(paasmoutput,init);
AppendToResourceList(Name,P,Len,Hash);
{ an empty ansi string is nil! }
if (p=nil) or (len=0) then
resourcestringlist^.concat(new(pai_const,init_32bit(0)))
else
begin
getdatalabel(l1);
resourcestringlist^.concat(new(pai_const_symbol,init(l1)));
{ first write the maximum size }
consts^.concat(new(pai_const,init_32bit(len)));
{ second write the real length }
consts^.concat(new(pai_const,init_32bit(len)));
{ redondent with maxlength but who knows ... (PM) }
{ third write use count (set to -1 for safety ) }
consts^.concat(new(pai_const,init_32bit(-1)));
consts^.concat(new(pai_label,init(l1)));
getmem(s,len+1);
move(p^,s^,len);
s[len]:=#0;
consts^.concat(new(pai_string,init_length_pchar(s,len)));
consts^.concat(new(pai_const,init_8bit(0)));
end;
resourcestringlist^.concat(new(pai_const,init_32bit(0)));
resourcestringlist^.concat(new(pai_const,init_32bit(hash)));
end;
Procedure WriteResourceFile(Filename : String);
Type
TMode = (quoted,unquoted);
Var F : Text;
Mode : TMode;
old : PresourceString;
C : char;
Col,i : longint;
Procedure Add(Const S : String);
begin
Write(F,S);
Col:=Col+length(s);
end;
begin
If resstrCount=0 then
exit;
FileName:=ForceExtension(lower(FileName),'.rst');
message1 (general_i_writingresourcefile,filename);
Assign(F,Filename);
{$i-}
Rewrite(f);
{$i+}
If IOresult<>0 then
begin
message(general_e_errorwritingresourcefile);
exit;
end;
While ResourceListRoot<>Nil do
With ResourceListRoot^ do
begin
writeln(f);
Writeln (f,'# hash value = ',hash);
col:=0;
Add(Name+'=');
Mode:=unquoted;
For I:=0 to Len-1 do
begin
C:=Value[i];
If (ord(C)>31) and (Ord(c)<=128) and (c<>'''') then
begin
If mode=Quoted then
Add(c)
else
begin
Add(''''+c);
mode:=quoted
end
end
else
begin
If Mode=quoted then
begin
Add('''');
mode:=unquoted;
end;
Add('#'+tostr(ord(c)));
end;
If Col>72 then
begin
if mode=quoted then
Write (F,'''');
Writeln(F,'+');
Col:=0;
Mode:=unQuoted;
end;
end;
if mode=quoted then writeln (f,'''');
Writeln(f);
Old :=ResourceListRoot;
ResourceListRoot:=old^.Next;
FreeMem(Old^.Value,Len);
Dispose(Old);
end;
close(f);
end;
end.
{
$Log$
Revision 1.4 1999-07-24 16:22:10 michael
+ Improved resourcestring handling
Revision 1.3 1999/07/24 15:12:58 michael
changes for resourcestrings
Revision 1.2 1999/07/22 20:04:58 michael
+ Added computehashvalue
Revision 1.1 1999/07/22 09:34:04 florian
+ initial revision
}