* $NAMESPACES directive

This commit is contained in:
Michael VAN CANNEYT 2023-02-03 17:28:28 +01:00 committed by Michaël Van Canneyt
parent c75aa72b8f
commit 64feb6a5cd
5 changed files with 113 additions and 21 deletions

View File

@ -174,6 +174,7 @@ interface
loaded_from : tmodule;
_exports : tlinkedlist;
dllscannerinputlist : TFPHashList;
localnamespacelist,
resourcefiles,
linkorderedsymbols : TCmdStrList;
linkunitofiles,
@ -241,6 +242,7 @@ interface
constructor create(LoadedFrom:TModule;const amodulename: string; const afilename:TPathStr;_is_unit:boolean);
destructor destroy;override;
procedure reset;virtual;
procedure loadlocalnamespacelist;
procedure adddependency(callermodule:tmodule);
procedure flagdependent(callermodule:tmodule);
procedure addimportedsym(sym:TSymEntry);
@ -572,6 +574,7 @@ implementation
localframeworksearchpath:=TSearchPathList.Create;
used_units:=TLinkedList.Create;
dependent_units:=TLinkedList.Create;
localnamespacelist:=TCmdStrList.Create;
resourcefiles:=TCmdStrList.Create;
linkorderedsymbols:=TCmdStrList.Create;
linkunitofiles:=TLinkContainer.Create;
@ -946,6 +949,26 @@ implementation
}
end;
procedure tmodule.loadlocalnamespacelist;
var
nsitem : TCmdStrListItem;
begin
// Copying local namespace list
if premodule_namespacelist.Count>0 then
begin
nsitem:=TCmdStrListItem(premodule_namespacelist.First);
while assigned(nsItem) do
begin
localnamespacelist.Concat(nsitem.Str);
nsItem:=TCmdStrListItem(nsitem.Next);
end;
premodule_namespacelist.Clear;
end;
current_namespacelist:=localnamespacelist;
end;
procedure tmodule.adddependency(callermodule:tmodule);
begin

View File

@ -562,10 +562,35 @@ var
result:=SearchPathList(UnitSearchPath,prefix);
end;
function SearchNamespaceList(const prefixes:TCmdStrList):boolean;
var
nsitem : TCmdStrListItem;
res : Boolean;
begin
res:=false;
nsitem:=TCmdStrListItem(prefixes.first);
while assigned(nsitem) do
begin
if not onlysource then
begin
res:=SearchPPUPaths(nsitem.str);
if res then
break;
end;
res:=SearchSourcePaths(nsitem.str);
if res then
break;
nsitem:=TCmdStrListItem(nsitem.next);
end;
if assigned(nsitem) then
nsprefix:=nsitem.str;
result:=res;
end;
var
fnd : boolean;
hs : TPathStr;
nsitem : TCmdStrListItem;
begin
if shortname then
filename:=FixFileName(Copy(realmodulename^,1,8))
@ -618,26 +643,11 @@ var
if not fnd then
begin
fnd:=SearchSourcePaths('');
// current_namespacelist is set to the current module's namespacelist.
if not fnd and assigned(current_namespacelist) and (current_namespacelist.count>0) then
fnd:=SearchNameSpaceList(current_namespacelist);
if not fnd and (namespacelist.count>0) then
begin
nsitem:=TCmdStrListItem(namespacelist.first);
while assigned(nsitem) do
begin
if not onlysource then
begin
fnd:=SearchPPUPaths(nsitem.str);
if fnd then
break;
end;
fnd:=SearchSourcePaths(nsitem.str);
if fnd then
break;
nsitem:=TCmdStrListItem(nsitem.next);
end;
if assigned(nsitem) then
nsprefix:=nsitem.str;
end;
fnd:=SearchNameSpaceList(namespacelist);
end;
search_unit:=fnd;
end;

View File

@ -316,8 +316,13 @@ interface
includesearchpath,
frameworksearchpath : TSearchPathList;
packagesearchpath : TSearchPathList;
{ list of default namespaces }
namespacelist : TCmdStrList;
// During scanning/parsing, a module may not yet be available.
// Scanner checks first current_namespacelist, then local_namespacelist
premodule_namespacelist, // always set: used as long as current_namespacelist is not correctly set.
current_namespacelist : TCmdStrList; // Set when parsing module to the current module's namespace.
{ contains tpackageentry entries }
packagelist : TFPHashList;
autoloadunits : string;
@ -378,6 +383,7 @@ interface
LinkLibraryAliases : TLinkStrMap;
LinkLibraryOrder : TLinkStrMap;
init_settings,
current_settings : tsettings;
@ -1653,6 +1659,8 @@ implementation
LinkLibraryOrder.Free;
packagesearchpath.Free;
namespacelist.Free;
premodule_namespacelist.Free;
current_namespacelist:=Nil;
end;
procedure InitGlobals;
@ -1694,7 +1702,8 @@ implementation
frameworksearchpath:=TSearchPathList.Create;
packagesearchpath:=TSearchPathList.Create;
namespacelist:=TCmdStrList.Create;
premodule_namespacelist:=TCmdStrList.Create;
current_namespacelist:=Nil;
{ Def file }
usewindowapi:=false;
description:='Compiled by FPC '+version_string+' - '+target_cpu_string;

View File

@ -1018,6 +1018,11 @@ type
if not(cs_compilesystem in current_settings.moduleswitches) and
(token=_USES) then
begin
// We do this as late as possible.
if Assigned(current_module) then
current_module.Loadlocalnamespacelist
else
current_namespacelist:=Nil;
loadunits(nil);
{ has it been compiled at a higher level ?}
if current_module.state=ms_compiled then
@ -1640,6 +1645,12 @@ type
{ ensure that no packages are picked up from the options }
packagelist.clear;
// There should always be a requires, except for the system package. So we load here
if Assigned(current_module) then
current_module.Loadlocalnamespacelist
else
current_namespacelist:=Nil;
{Read the packages used by the package we compile.}
if (token=_ID) and (idtoken=_REQUIRES) then
begin
@ -2188,6 +2199,11 @@ type
{ Load the units used by the program we compile. }
if token=_USES then
begin
// We can do this here: if there is no uses then the namespace directive makes no sense.
if Assigned(current_module) then
current_module.Loadlocalnamespacelist
else
current_namespacelist:=Nil;
loadunits(nil);
consume_semicolon_after_uses:=true;
end

View File

@ -1019,6 +1019,39 @@ unit scandir;
end;
procedure dir_namespaces;
{ add namespaces to the local namespace list }
var
s : string;
begin
if not current_module.in_global then
Message(scan_w_switch_is_global)
else
begin
current_scanner.skipspace;
current_scanner.readstring;
s:=orgpattern;
While (s<>'') do
begin
// We may not yet have a correct module namespacelist.
if assigned(current_namespacelist) then
current_namespacelist.Insert(s)
else // copied when correct module is activated
premodule_namespacelist.Insert(s);
s:='';
if c=',' then
begin
current_scanner.readchar;
current_scanner.skipspace;
current_scanner.readstring;
s:=orgpattern;
end;
end;
end;
end;
procedure dir_namespace;
var
s : string;
@ -2029,6 +2062,7 @@ unit scandir;
AddDirective('MODE',directive_all, @dir_mode);
AddDirective('MODESWITCH',directive_all, @dir_modeswitch);
AddDirective('NAMESPACE',directive_all, @dir_namespace);
AddDirective('NAMESPACES',directive_all, @dir_namespaces);
AddDirective('NODEFINE',directive_all, @dir_nodefine);
AddDirective('NOTE',directive_all, @dir_note);
AddDirective('NOTES',directive_all, @dir_notes);