mirror of
https://gitlab.com/freepascal.org/fpc/source.git
synced 2025-08-17 03:19:29 +02:00
+ Mantis #19651: Generate table of typed string constants which are initialized with resourcestrings, so they are updated when SetResourceStrings or SetUnitResourceStrings is called.
git-svn-id: trunk@18968 -
This commit is contained in:
parent
dbd33fd6a5
commit
689d4b3ecc
1
.gitattributes
vendored
1
.gitattributes
vendored
@ -11739,6 +11739,7 @@ tests/webtbs/tw1950.pp svneol=native#text/plain
|
|||||||
tests/webtbs/tw19548.pp svneol=native#text/pascal
|
tests/webtbs/tw19548.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw19555.pp svneol=native#text/pascal
|
tests/webtbs/tw19555.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw1964.pp svneol=native#text/plain
|
tests/webtbs/tw1964.pp svneol=native#text/plain
|
||||||
|
tests/webtbs/tw19651.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw19700.pp svneol=native#text/plain
|
tests/webtbs/tw19700.pp svneol=native#text/plain
|
||||||
tests/webtbs/tw19851a.pp svneol=native#text/pascal
|
tests/webtbs/tw19851a.pp svneol=native#text/pascal
|
||||||
tests/webtbs/tw19851b.pp svneol=native#text/pascal
|
tests/webtbs/tw19851b.pp svneol=native#text/pascal
|
||||||
|
@ -155,6 +155,7 @@ interface
|
|||||||
AsmLists : array[TAsmListType] of TAsmList;
|
AsmLists : array[TAsmListType] of TAsmList;
|
||||||
CurrAsmList : TAsmList;
|
CurrAsmList : TAsmList;
|
||||||
WideInits : TLinkedList;
|
WideInits : TLinkedList;
|
||||||
|
ResStrInits : TLinkedList;
|
||||||
{ hash tables for reusing constant storage }
|
{ hash tables for reusing constant storage }
|
||||||
ConstPools : array[TConstPoolType] of THashSet;
|
ConstPools : array[TConstPoolType] of THashSet;
|
||||||
constructor create(const n:string);
|
constructor create(const n:string);
|
||||||
@ -180,8 +181,8 @@ interface
|
|||||||
TTCInitItem = class(TLinkedListItem)
|
TTCInitItem = class(TLinkedListItem)
|
||||||
sym: tsym;
|
sym: tsym;
|
||||||
offset: aint;
|
offset: aint;
|
||||||
datalabel: TAsmLabel;
|
datalabel: TAsmSymbol;
|
||||||
constructor Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
|
constructor Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol);
|
||||||
end;
|
end;
|
||||||
|
|
||||||
var
|
var
|
||||||
@ -256,7 +257,7 @@ implementation
|
|||||||
*****************************************************************************}
|
*****************************************************************************}
|
||||||
|
|
||||||
|
|
||||||
constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmLabel);
|
constructor TTCInitItem.Create(asym: tsym; aoffset: aint; alabel: TAsmSymbol);
|
||||||
begin
|
begin
|
||||||
inherited Create;
|
inherited Create;
|
||||||
sym:=asym;
|
sym:=asym;
|
||||||
@ -334,6 +335,7 @@ implementation
|
|||||||
for hal:=low(TAsmListType) to high(TAsmListType) do
|
for hal:=low(TAsmListType) to high(TAsmListType) do
|
||||||
AsmLists[hal]:=TAsmList.create;
|
AsmLists[hal]:=TAsmList.create;
|
||||||
WideInits :=TLinkedList.create;
|
WideInits :=TLinkedList.create;
|
||||||
|
ResStrInits:=TLinkedList.create;
|
||||||
{ CFI }
|
{ CFI }
|
||||||
FAsmCFI:=CAsmCFI.Create;
|
FAsmCFI:=CAsmCFI.Create;
|
||||||
end;
|
end;
|
||||||
@ -365,6 +367,7 @@ implementation
|
|||||||
{$ifdef MEMDEBUG}
|
{$ifdef MEMDEBUG}
|
||||||
memasmlists.start;
|
memasmlists.start;
|
||||||
{$endif}
|
{$endif}
|
||||||
|
ResStrInits.free;
|
||||||
WideInits.free;
|
WideInits.free;
|
||||||
for hal:=low(TAsmListType) to high(TAsmListType) do
|
for hal:=low(TAsmListType) to high(TAsmListType) do
|
||||||
AsmLists[hal].free;
|
AsmLists[hal].free;
|
||||||
|
@ -2488,6 +2488,7 @@ begin
|
|||||||
def_system_macro('FPC_HAS_RIP_RELATIVE');
|
def_system_macro('FPC_HAS_RIP_RELATIVE');
|
||||||
{$endif x86_64}
|
{$endif x86_64}
|
||||||
def_system_macro('FPC_HAS_CEXTENDED');
|
def_system_macro('FPC_HAS_CEXTENDED');
|
||||||
|
def_system_macro('FPC_HAS_RESSTRINITS');
|
||||||
|
|
||||||
{ these cpus have an inline rol/ror implementaion }
|
{ these cpus have an inline rol/ror implementaion }
|
||||||
{$if defined(x86) or defined(arm) or defined(powerpc) or defined(powerpc64)}
|
{$if defined(x86) or defined(arm) or defined(powerpc) or defined(powerpc64)}
|
||||||
|
@ -230,15 +230,15 @@ implementation
|
|||||||
ltvTable.Free;
|
ltvTable.Free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure InsertWideInits;
|
procedure InsertRuntimeInits(const prefix:string;list:TLinkedList;unitflag:cardinal);
|
||||||
var
|
var
|
||||||
s: string;
|
s: string;
|
||||||
item: TTCInitItem;
|
item: TTCInitItem;
|
||||||
begin
|
begin
|
||||||
item:=TTCInitItem(current_asmdata.WideInits.First);
|
item:=TTCInitItem(list.First);
|
||||||
if item=nil then
|
if item=nil then
|
||||||
exit;
|
exit;
|
||||||
s:=make_mangledname('WIDEINITS',current_module.localsymtable,'');
|
s:=make_mangledname(prefix,current_module.localsymtable,'');
|
||||||
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
||||||
new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
|
new_section(current_asmdata.asmlists[al_globals],sec_data,s,sizeof(pint));
|
||||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
|
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(s,AT_DATA,0));
|
||||||
@ -256,44 +256,63 @@ implementation
|
|||||||
{ end-of-list marker }
|
{ end-of-list marker }
|
||||||
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
|
current_asmdata.asmlists[al_globals].concat(Tai_const.Create_sym(nil));
|
||||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
|
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(s));
|
||||||
current_module.flags:=current_module.flags or uf_wideinits;
|
current_module.flags:=current_module.flags or unitflag;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
procedure InsertWideInitsTablesTable;
|
procedure InsertRuntimeInitsTablesTable(const prefix,tablename:string;unitflag:cardinal);
|
||||||
var
|
var
|
||||||
hp: tused_unit;
|
hp: tused_unit;
|
||||||
lwiTables: TAsmList;
|
hlist: TAsmList;
|
||||||
count: longint;
|
count: longint;
|
||||||
begin
|
begin
|
||||||
lwiTables:=TAsmList.Create;
|
hlist:=TAsmList.Create;
|
||||||
count:=0;
|
count:=0;
|
||||||
hp:=tused_unit(usedunits.first);
|
hp:=tused_unit(usedunits.first);
|
||||||
while assigned(hp) do
|
while assigned(hp) do
|
||||||
begin
|
begin
|
||||||
if (hp.u.flags and uf_wideinits)=uf_wideinits then
|
if (hp.u.flags and unitflag)=unitflag then
|
||||||
begin
|
begin
|
||||||
lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',hp.u.globalsymtable,''),0));
|
hlist.concat(Tai_const.Createname(make_mangledname(prefix,hp.u.globalsymtable,''),0));
|
||||||
inc(count);
|
inc(count);
|
||||||
end;
|
end;
|
||||||
hp:=tused_unit(hp.next);
|
hp:=tused_unit(hp.next);
|
||||||
end;
|
end;
|
||||||
{ Add program widestring consts, if any }
|
{ Add items from program, if any }
|
||||||
if (current_module.flags and uf_wideinits)=uf_wideinits then
|
if (current_module.flags and unitflag)=unitflag then
|
||||||
begin
|
begin
|
||||||
lwiTables.concat(Tai_const.Createname(make_mangledname('WIDEINITS',current_module.localsymtable,''),0));
|
hlist.concat(Tai_const.Createname(make_mangledname(prefix,current_module.localsymtable,''),0));
|
||||||
inc(count);
|
inc(count);
|
||||||
end;
|
end;
|
||||||
{ Insert TableCount at start }
|
{ Insert TableCount at start }
|
||||||
lwiTables.insert(Tai_const.Create_32bit(count));
|
hlist.insert(Tai_const.Create_32bit(count));
|
||||||
{ insert in data segment }
|
{ insert in data segment }
|
||||||
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
maybe_new_object_file(current_asmdata.asmlists[al_globals]);
|
||||||
new_section(current_asmdata.asmlists[al_globals],sec_data,'FPC_WIDEINITTABLES',sizeof(pint));
|
new_section(current_asmdata.asmlists[al_globals],sec_data,tablename,sizeof(pint));
|
||||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global('FPC_WIDEINITTABLES',AT_DATA,0));
|
current_asmdata.asmlists[al_globals].concat(Tai_symbol.Createname_global(tablename,AT_DATA,0));
|
||||||
current_asmdata.asmlists[al_globals].concatlist(lwiTables);
|
current_asmdata.asmlists[al_globals].concatlist(hlist);
|
||||||
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname('FPC_WIDEINITTABLES'));
|
current_asmdata.asmlists[al_globals].concat(Tai_symbol_end.Createname(tablename));
|
||||||
lwiTables.free;
|
hlist.free;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
procedure InsertWideInits;
|
||||||
|
begin
|
||||||
|
InsertRuntimeInits('WIDEINITS',current_asmdata.WideInits,uf_wideinits);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InsertResStrInits;
|
||||||
|
begin
|
||||||
|
InsertRuntimeInits('RESSTRINITS',current_asmdata.ResStrInits,uf_resstrinits);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InsertWideInitsTablesTable;
|
||||||
|
begin
|
||||||
|
InsertRuntimeInitsTablesTable('WIDEINITS','FPC_WIDEINITTABLES',uf_wideinits);
|
||||||
|
end;
|
||||||
|
|
||||||
|
procedure InsertResStrTablesTable;
|
||||||
|
begin
|
||||||
|
InsertRuntimeInitsTablesTable('RESSTRINITS','FPC_RESSTRINITTABLES',uf_resstrinits);
|
||||||
|
end;
|
||||||
|
|
||||||
Function CheckResourcesUsed : boolean;
|
Function CheckResourcesUsed : boolean;
|
||||||
var
|
var
|
||||||
@ -1387,6 +1406,9 @@ implementation
|
|||||||
{ Widestring typed constants }
|
{ Widestring typed constants }
|
||||||
InsertWideInits;
|
InsertWideInits;
|
||||||
|
|
||||||
|
{ Resourcestring references }
|
||||||
|
InsertResStrInits;
|
||||||
|
|
||||||
{ generate debuginfo }
|
{ generate debuginfo }
|
||||||
if (cs_debuginfo in current_settings.moduleswitches) then
|
if (cs_debuginfo in current_settings.moduleswitches) then
|
||||||
current_debuginfo.inserttypeinfo;
|
current_debuginfo.inserttypeinfo;
|
||||||
@ -2395,11 +2417,15 @@ implementation
|
|||||||
{ Windows widestring needing initialization }
|
{ Windows widestring needing initialization }
|
||||||
InsertWideInits;
|
InsertWideInits;
|
||||||
|
|
||||||
|
{ Resourcestring references (const foo:string=someresourcestring) }
|
||||||
|
InsertResStrInits;
|
||||||
|
|
||||||
{ insert Tables and StackLength }
|
{ insert Tables and StackLength }
|
||||||
InsertInitFinalTable;
|
InsertInitFinalTable;
|
||||||
InsertThreadvarTablesTable;
|
InsertThreadvarTablesTable;
|
||||||
InsertResourceTablesTable;
|
InsertResourceTablesTable;
|
||||||
InsertWideInitsTablesTable;
|
InsertWideInitsTablesTable;
|
||||||
|
InsertResStrTablesTable;
|
||||||
InsertMemorySizes;
|
InsertMemorySizes;
|
||||||
|
|
||||||
{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
|
{$ifdef FPC_HAS_SYSTEMS_INTERRUPT_TABLE}
|
||||||
|
@ -160,6 +160,7 @@ const
|
|||||||
uf_has_dwarf_debuginfo = $200000; { this unit has dwarf debuginfo generated }
|
uf_has_dwarf_debuginfo = $200000; { this unit has dwarf debuginfo generated }
|
||||||
uf_wideinits = $400000; { this unit has winlike widestring typed constants }
|
uf_wideinits = $400000; { this unit has winlike widestring typed constants }
|
||||||
uf_classinits = $800000; { this unit has class constructors/destructors }
|
uf_classinits = $800000; { this unit has class constructors/destructors }
|
||||||
|
uf_resstrinits = $1000000; { this unit has string consts referencing resourcestrings }
|
||||||
|
|
||||||
type
|
type
|
||||||
{ bestreal is defined based on the target architecture }
|
{ bestreal is defined based on the target architecture }
|
||||||
|
@ -656,6 +656,7 @@ implementation
|
|||||||
ll : tasmlabel;
|
ll : tasmlabel;
|
||||||
ca : pchar;
|
ca : pchar;
|
||||||
winlike : boolean;
|
winlike : boolean;
|
||||||
|
hsym : tconstsym;
|
||||||
begin
|
begin
|
||||||
n:=comp_expr(true,false);
|
n:=comp_expr(true,false);
|
||||||
{ load strval and strlength of the constant tree }
|
{ load strval and strlength of the constant tree }
|
||||||
@ -691,8 +692,21 @@ implementation
|
|||||||
end
|
end
|
||||||
else if is_constresourcestringnode(n) then
|
else if is_constresourcestringnode(n) then
|
||||||
begin
|
begin
|
||||||
strval:=pchar(tconstsym(tloadnode(n).symtableentry).value.valueptr);
|
hsym:=tconstsym(tloadnode(n).symtableentry);
|
||||||
strlength:=tconstsym(tloadnode(n).symtableentry).value.len;
|
strval:=pchar(hsym.value.valueptr);
|
||||||
|
strlength:=hsym.value.len;
|
||||||
|
{ Link the string constant to its initializing resourcestring,
|
||||||
|
enabling it to be (re)translated at runtime.
|
||||||
|
}
|
||||||
|
if (hr.origsym.owner.symtablelevel<=main_program_level) or
|
||||||
|
(hr.origblock=bt_const) then
|
||||||
|
begin
|
||||||
|
current_asmdata.ResStrInits.Concat(
|
||||||
|
TTCInitItem.Create(hr.origsym,hr.offset,
|
||||||
|
current_asmdata.RefAsmSymbol(make_mangledname('RESSTR',hsym.owner,hsym.name)))
|
||||||
|
);
|
||||||
|
Include(hr.origsym.varoptions,vo_force_finalize);
|
||||||
|
end;
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
begin
|
begin
|
||||||
|
@ -270,7 +270,7 @@ type
|
|||||||
str : string[30];
|
str : string[30];
|
||||||
end;
|
end;
|
||||||
const
|
const
|
||||||
flagopts=23;
|
flagopts=24;
|
||||||
flagopt : array[1..flagopts] of tflagopt=(
|
flagopt : array[1..flagopts] of tflagopt=(
|
||||||
(mask: $1 ;str:'init'),
|
(mask: $1 ;str:'init'),
|
||||||
(mask: $2 ;str:'final'),
|
(mask: $2 ;str:'final'),
|
||||||
@ -296,7 +296,8 @@ const
|
|||||||
(mask: $80000 ;str:'has_resourcefiles'),
|
(mask: $80000 ;str:'has_resourcefiles'),
|
||||||
(mask: $100000 ;str:'has_exports'),
|
(mask: $100000 ;str:'has_exports'),
|
||||||
(mask: $400000 ;str:'has_wideinits'),
|
(mask: $400000 ;str:'has_wideinits'),
|
||||||
(mask: $800000 ;str:'has_classinits')
|
(mask: $800000 ;str:'has_classinits'),
|
||||||
|
(mask: $1000000 ;str:'has_resstrinits')
|
||||||
);
|
);
|
||||||
var
|
var
|
||||||
i,ntflags : longint;
|
i,ntflags : longint;
|
||||||
|
@ -312,6 +312,39 @@ Type
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
{ Support for string constants initialized with resourcestrings }
|
||||||
|
{$ifdef FPC_HAS_RESSTRINITS}
|
||||||
|
PResStrInitEntry = ^TResStrInitEntry;
|
||||||
|
TResStrInitEntry = record
|
||||||
|
Addr: PPointer;
|
||||||
|
Data: PResourceStringRecord;
|
||||||
|
end;
|
||||||
|
|
||||||
|
TResStrInitTable = packed record
|
||||||
|
Count: longint;
|
||||||
|
Tables: packed array[1..32767] of PResStrInitEntry;
|
||||||
|
end;
|
||||||
|
|
||||||
|
var
|
||||||
|
ResStrInitTable : TResStrInitTable; external name 'FPC_RESSTRINITTABLES';
|
||||||
|
|
||||||
|
procedure UpdateResourceStringRefs;
|
||||||
|
var
|
||||||
|
i: Longint;
|
||||||
|
ptable: PResStrInitEntry;
|
||||||
|
begin
|
||||||
|
for i:=1 to ResStrInitTable.Count do
|
||||||
|
begin
|
||||||
|
ptable:=ResStrInitTable.Tables[i];
|
||||||
|
while Assigned(ptable^.Addr) do
|
||||||
|
begin
|
||||||
|
AnsiString(ptable^.Addr^):=ptable^.Data^.CurrentValue;
|
||||||
|
Inc(ptable);
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
end;
|
||||||
|
{$endif FPC_HAS_RESSTRINITS}
|
||||||
|
|
||||||
Var
|
Var
|
||||||
ResourceStringTable : TResourceStringTableList; External Name 'FPC_RESOURCESTRINGTABLES';
|
ResourceStringTable : TResourceStringTableList; External Name 'FPC_RESOURCESTRINGTABLES';
|
||||||
|
|
||||||
@ -337,6 +370,9 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$ifdef FPC_HAS_RESSTRINITS}
|
||||||
|
UpdateResourceStringRefs;
|
||||||
|
{$endif FPC_HAS_RESSTRINITS}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
@ -366,6 +402,11 @@ begin
|
|||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
end;
|
end;
|
||||||
|
{$ifdef FPC_HAS_RESSTRINITS}
|
||||||
|
{ Resourcestrings of one unit may be referenced from other units,
|
||||||
|
so updating everything is the only option. }
|
||||||
|
UpdateResourceStringRefs;
|
||||||
|
{$endif FPC_HAS_RESSTRINITS}
|
||||||
end;
|
end;
|
||||||
|
|
||||||
|
|
||||||
|
24
tests/webtbs/tw19651.pp
Normal file
24
tests/webtbs/tw19651.pp
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
{$mode objfpc}{$h+}
|
||||||
|
{$APPTYPE CONSOLE}
|
||||||
|
|
||||||
|
uses
|
||||||
|
SysUtils;
|
||||||
|
|
||||||
|
resourcestring
|
||||||
|
SSunday = 'Sunday';
|
||||||
|
|
||||||
|
const
|
||||||
|
SDays: array[0..0] of string = (SSunday);
|
||||||
|
|
||||||
|
function Translate(Name,Value : AnsiString; Hash : Longint; arg:pointer) : AnsiString;
|
||||||
|
begin
|
||||||
|
Result := 'dimanche';
|
||||||
|
end;
|
||||||
|
|
||||||
|
begin
|
||||||
|
SetResourceStrings(@Translate, nil);
|
||||||
|
WriteLn(SSunday);
|
||||||
|
WriteLn(SDays[0]);
|
||||||
|
if SDays[0]<>'dimanche' then
|
||||||
|
Halt(1);
|
||||||
|
end.
|
Loading…
Reference in New Issue
Block a user