Просмотр исходного кода

* unit loading changed to first register units and load them
afterwards. This is needed to support uses xxx in yyy correctly
* unit dependency check fixed

peter 22 лет назад
Родитель
Сommit
bbf8bddbb4

+ 7 - 2
compiler/browcol.pas

@@ -1646,7 +1646,7 @@ begin
            puu:=tused_unit(hp.used_units.first);
            while (puu<>nil) do
            begin
-             PM:=SearchModule(puu.name^);
+             PM:=SearchModule(puu.u.modulename^);
              if Assigned(PM) then
                UnitS^.AddUsedUnit(PM);
              puu:=tused_unit(puu.next);
@@ -2118,7 +2118,12 @@ begin
 end.
 {
   $Log$
-  Revision 1.31  2002-11-27 20:04:10  peter
+  Revision 1.32  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.31  2002/11/27 20:04:10  peter
     * tvarsym.get_push_size replaced by paramanager.push_size
 
   Revision 1.30  2002/11/24 18:17:29  carl

+ 8 - 1
compiler/comphook.pas

@@ -252,6 +252,8 @@ begin
         hs:=errorstr;
       if (status.verbosity and Level)=V_Fatal then
         hs:=fatalstr;
+      if (status.verbosity and Level)=V_Used then
+        hs:=PadSpace('('+status.currentmodule+')',10);
     end
   else
     begin
@@ -379,7 +381,12 @@ end;
 end.
 {
   $Log$
-  Revision 1.22  2002-12-20 18:14:23  peter
+  Revision 1.23  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.22  2002/12/20 18:14:23  peter
     * traceback added in EXTDEBUG mode for internalerror
 
   Revision 1.21  2002/11/15 01:58:46  peter

+ 7 - 2
compiler/defcmp.pas

@@ -1139,7 +1139,7 @@ implementation
 
     function proc_to_procvar_equal(def1:tabstractprocdef;def2:tprocvardef):tequaltype;
       const
-        po_comp = po_compatibility_options-[po_methodpointer,po_classmethod];
+        po_comp = po_compatibility_options-[po_methodpointer];
       var
         ismethod : boolean;
         eq : tequaltype;
@@ -1196,7 +1196,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.11  2002-12-27 15:26:12  peter
+  Revision 1.12  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.11  2002/12/27 15:26:12  peter
     * procvar compare with 2 ints did not check the integer size
 
   Revision 1.10  2002/12/23 22:22:16  peter

+ 26 - 4
compiler/finput.pas

@@ -113,11 +113,28 @@ interface
                                 TModuleBase
  ****************************************************************************}
 
-       tmodulebase = class(TLinkedListItem)
+     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 }
-          in_compile    : boolean;  { is it being compiled ?? }
+          state         : tmodulestate;
           { sources }
           sourcefiles   : tinputfilemanager;
           { paths and filenames }
@@ -650,7 +667,7 @@ uses
         outputpath:=nil;
         path:=nil;
         { status }
-        in_compile:=false;
+        state:=ms_registered;
         { unit index }
         inc(global_unit_count);
         unit_index:=global_unit_count;
@@ -687,7 +704,12 @@ uses
 end.
 {
   $Log$
-  Revision 1.20  2002-11-15 01:58:46  peter
+  Revision 1.21  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.20  2002/11/15 01:58:46  peter
     * merged changes from 1.0.7 up to 04-11
       - -V option for generating bug report tracing
       - more tracing for option parsing

+ 107 - 99
compiler/fmodule.pas

@@ -46,51 +46,45 @@ interface
 
 
     type
-       trecompile_reason = (rr_unknown,
-         rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
-       );
-
-       TExternalsItem=class(TLinkedListItem)
-       public
-         found : longbool;
-         data  : pstring;
-         constructor Create(const s:string);
-         Destructor Destroy;override;
-       end;
+      trecompile_reason = (rr_unknown,
+        rr_noppu,rr_sourcenewer,rr_build,rr_crcchanged
+      );
+
+      TExternalsItem=class(TLinkedListItem)
+      public
+        found : longbool;
+        data  : pstring;
+        constructor Create(const s:string);
+        Destructor Destroy;override;
+      end;
 
-       tlinkcontaineritem=class(tlinkedlistitem)
-       public
-          data : pstring;
-          needlink : cardinal;
-          constructor Create(const s:string;m:cardinal);
-          destructor Destroy;override;
-       end;
+      tlinkcontaineritem=class(tlinkedlistitem)
+      public
+         data : pstring;
+         needlink : cardinal;
+         constructor Create(const s:string;m:cardinal);
+         destructor Destroy;override;
+      end;
 
-       tlinkcontainer=class(tlinkedlist)
-          procedure add(const s : string;m:cardinal);
-          function get(var m:cardinal) : string;
-          function getusemask(mask:cardinal) : string;
-          function find(const s:string):boolean;
-       end;
+      tlinkcontainer=class(tlinkedlist)
+         procedure add(const s : string;m:cardinal);
+         function get(var m:cardinal) : string;
+         function getusemask(mask:cardinal) : string;
+         function find(const s:string):boolean;
+      end;
 
-{$ifndef NEWMAP}
-       tunitmap = array[0..maxunits-1] of pointer;
-       punitmap = ^tunitmap;
-{$else NEWMAP}
-       tunitmap = array[0..maxunits-1] of tmodule;
-       punitmap = ^tunitmap;
-{$endif NEWMAP}
+      tmodule = class;
+      tused_unit = class;
+
+      tunitmap = array[0..maxunits-1] of tmodule;
+      punitmap = ^tunitmap;
 
       tmodule = class(tmodulebase)
-        compiled,                 { unit is already compiled }
         do_reload,                { force reloading of the unit }
         do_compile,               { need to compile the sources }
         sources_avail,            { if all sources are reachable }
-        sources_checked,          { if there is already done a check for the sources }
         is_unit,
-        in_second_compile,        { is this unit being compiled for the 2nd time? }
-        in_second_load,           { is this unit PPU loaded a 2nd time? }
-        in_implementation,        { processing the implementation part? }
+        in_interface,             { processing the implementation part? }
         in_global     : boolean;  { allow global settings }
         recompile_reason : trecompile_reason;  { the reason why the unit should be recompiled }
         crc,
@@ -132,23 +126,21 @@ interface
         constructor create(LoadedFrom:TModule;const s:string;_is_unit:boolean);
         destructor destroy;override;
         procedure reset;virtual;
+        procedure adddependency(callermodule:tmodule);
+        procedure flagdependent(callermodule:tmodule);
+        function  addusedunit(hp:tmodule;inuses:boolean):tused_unit;
         procedure numberunits;
       end;
 
        tused_unit = class(tlinkedlistitem)
           unitid          : longint;
-          name            : pstring;
-          realname        : pstring;
           checksum,
           interface_checksum : cardinal;
-          loaded          : boolean;
           in_uses,
           in_interface,
           is_stab_written : boolean;
           u               : tmodule;
-          constructor create(_u : tmodule;intface:boolean);
-          constructor create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
-          destructor destroy;override;
+          constructor create(_u : tmodule;intface,inuses:boolean);
        end;
 
        tdependent_unit = class(tlinkedlistitem)
@@ -306,41 +298,23 @@ uses
                               TUSED_UNIT
  ****************************************************************************}
 
-    constructor tused_unit.create(_u : tmodule;intface:boolean);
+    constructor tused_unit.create(_u : tmodule;intface,inuses:boolean);
       begin
         u:=_u;
         in_interface:=intface;
-        in_uses:=false;
-        is_stab_written:=false;
-        loaded:=true;
-        name:=stringdup(_u.modulename^);
-        realname:=stringdup(_u.realmodulename^);
-        checksum:=_u.crc;
-        interface_checksum:=_u.interface_crc;
-        unitid:=0;
-      end;
-
-
-    constructor tused_unit.create_to_load(const n:string;c,intfc:cardinal;intface:boolean);
-      begin
-        u:=nil;
-        in_interface:=intface;
-        in_uses:=false;
+        in_uses:=inuses;
         is_stab_written:=false;
-        loaded:=false;
-        name:=stringdup(upper(n));
-        realname:=stringdup(n);
-        checksum:=c;
-        interface_checksum:=intfc;
         unitid:=0;
-      end;
-
-
-    destructor tused_unit.destroy;
-      begin
-        stringdispose(realname);
-        stringdispose(name);
-        inherited destroy;
+        if _u.state=ms_compiled then
+         begin
+           checksum:=u.crc;
+           interface_checksum:=u.interface_crc;
+         end
+        else
+         begin
+           checksum:=0;
+           interface_checksum:=0;
+         end;
       end;
 
 
@@ -403,12 +377,8 @@ uses
         unitcount:=1;
         do_compile:=false;
         sources_avail:=true;
-        sources_checked:=false;
-        compiled:=false;
         recompile_reason:=rr_unknown;
-        in_second_load:=false;
-        in_second_compile:=false;
-        in_implementation:=false;
+        in_interface:=true;
         in_global:=true;
         is_unit:=_is_unit;
         islibrary:=false;
@@ -489,8 +459,6 @@ uses
 
 
     procedure tmodule.reset;
-      var
-         pm : tdependent_unit;
       begin
         if assigned(scanner) then
           begin
@@ -528,19 +496,6 @@ uses
         externals:=tlinkedlist.create;
         used_units.free;
         used_units:=TLinkedList.Create;
-        { all units that depend on this one must be recompiled ! }
-        pm:=tdependent_unit(dependent_units.first);
-        while assigned(pm) do
-          begin
-            if pm.u.in_second_compile then
-             Comment(v_debug,'No reload already in second compile: '+pm.u.modulename^)
-            else
-             begin
-               pm.u.do_reload:=true;
-               Comment(v_debug,'Reloading '+pm.u.modulename^+' needed because '+modulename^+' is reloaded');
-             end;
-            pm:=tdependent_unit(pm.next);
-          end;
         dependent_units.free;
         dependent_units:=TLinkedList.Create;
         resourcefiles.Free;
@@ -559,18 +514,66 @@ uses
         linkothersharedlibs:=TLinkContainer.Create;
         uses_imports:=false;
         do_compile:=false;
-        { sources_avail:=true;
-        should not be changed PM }
-        compiled:=false;
-        in_implementation:=false;
+        in_interface:=true;
         in_global:=true;
         crc:=0;
         interface_crc:=0;
         flags:=0;
-        {loaded_from:=nil;
-        should not be changed PFV }
         unitcount:=1;
         recompile_reason:=rr_unknown;
+        {
+          The following fields should not
+          be reset:
+           mainsource
+           loaded_from
+           state
+           sources_avail
+        }
+      end;
+
+
+    procedure tmodule.adddependency(callermodule:tmodule);
+      begin
+        { This is not needed for programs }
+        if not callermodule.is_unit then
+          exit;
+        Comment(V_Used,'Add dependency for '+callermodule.modulename^+' to '+modulename^);
+        dependent_units.concat(tdependent_unit.create(callermodule));
+      end;
+
+
+    procedure tmodule.flagdependent(callermodule:tmodule);
+      var
+        pm : tdependent_unit;
+      begin
+        { flag all units that depend on this unit for reloading }
+        pm:=tdependent_unit(current_module.dependent_units.first);
+        while assigned(pm) do
+         begin
+           { We do not have to reload the unit that wants to load
+             this unit }
+           if pm.u=callermodule then
+            Comment(v_used,'No reload, is caller: '+pm.u.modulename^)
+           else
+            if pm.u.state=ms_second_compile then
+             Comment(v_used,'No reload, already in second compile: '+pm.u.modulename^)
+           else
+            begin
+              pm.u.do_reload:=true;
+              Comment(v_used,'Flag for reload '+pm.u.modulename^);
+            end;
+           pm:=tdependent_unit(pm.next);
+         end;
+      end;
+
+
+    function tmodule.addusedunit(hp:tmodule;inuses:boolean):tused_unit;
+      var
+        pu : tused_unit;
+      begin
+        pu:=tused_unit.create(hp,in_interface,inuses);
+        used_units.concat(pu);
+        addusedunit:=pu;
       end;
 
 
@@ -607,7 +610,12 @@ uses
 end.
 {
   $Log$
-  Revision 1.31  2002-12-07 14:27:07  carl
+  Revision 1.32  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.31  2002/12/07 14:27:07  carl
     * 3% memory optimization
     * changed some types
     + added type checking with different size for call node and for

+ 274 - 267
compiler/fppu.pas

@@ -40,6 +40,7 @@ interface
     type
        tppumodule = class(tmodule)
           ppufile    : tcompilerppufile; { the PPU file }
+          sourcefn   : pstring; { Source specified with "uses .. in '..'" }
 {$ifdef Test_Double_checksum}
           crc_array  : pointer;
           crc_size   : longint;
@@ -50,11 +51,11 @@ interface
           destructor destroy;override;
           procedure reset;override;
           function  openppu:boolean;
-          function  search_unit(const n : string;const fn:string;onlysource:boolean):boolean;
           procedure getppucrc;
           procedure writeppu;
           procedure loadppu;
        private
+          function  search_unit(onlysource,shortname:boolean):boolean;
           procedure load_interface;
           procedure load_implementation;
           procedure load_symtable_refs;
@@ -73,8 +74,7 @@ interface
           procedure readasmsymbols;
        end;
 
-
-    function loadunit(const s : stringid;const fn:string) : tmodule;
+    function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
 
 
 implementation
@@ -95,17 +95,7 @@ uses
       begin
         inherited create(LoadedFrom,s,_is_unit);
         ppufile:=nil;
-      { search the PPU file if it is an unit }
-        if is_unit then
-         begin
-           { use the realmodulename so we can also find a case sensitive
-             source filename }
-           search_unit(realmodulename^,fn,false);
-           { it the sources_available is changed then we know that
-             the sources aren't available }
-           if not sources_avail then
-            sources_checked:=true;
-         end;
+        sourcefn:=stringdup(fn);
       end;
 
 
@@ -207,7 +197,7 @@ uses
       end;
 
 
-    function tppumodule.search_unit(const n : string;const fn:string;onlysource:boolean):boolean;
+    function tppumodule.search_unit(onlysource,shortname:boolean):boolean;
       var
          singlepathstring,
          filename : string;
@@ -300,7 +290,10 @@ uses
          fnd : boolean;
          hs  : string;
        begin
-         filename:=FixFileName(n);
+         if shortname then
+          filename:=FixFileName(Copy(realmodulename^,1,8))
+         else
+          filename:=FixFileName(realmodulename^);
          { try to find unit
             1. look for ppu in cwd
             2. look for ppu in outputpath if set, this is tp7 compatible (PFV)
@@ -315,16 +308,16 @@ uses
             if (not fnd) and (outputpath^<>'') then
              fnd:=PPUSearchPath(outputpath^);
            end;
-         if (not fnd) and (fn<>'') then
+         if (not fnd) and (sourcefn^<>'') then
           begin
             { the full filename is specified so we can't use here the
               searchpath (PFV) }
-            Message1(unit_t_unitsearch,AddExtension(fn,target_info.sourceext));
-            fnd:=FindFile(AddExtension(fn,target_info.sourceext),'',hs);
+            Message1(unit_t_unitsearch,AddExtension(sourcefn^,target_info.sourceext));
+            fnd:=FindFile(AddExtension(sourcefn^,target_info.sourceext),'',hs);
             if not fnd then
              begin
-               Message1(unit_t_unitsearch,AddExtension(fn,target_info.pasext));
-               fnd:=FindFile(AddExtension(fn,target_info.pasext),'',hs);
+               Message1(unit_t_unitsearch,AddExtension(sourcefn^,target_info.pasext));
+               fnd:=FindFile(AddExtension(sourcefn^,target_info.pasext),'',hs);
              end;
             if fnd then
              begin
@@ -336,18 +329,12 @@ uses
                SetFileName(hs,false);
              end;
           end;
-          if(not fnd)and Assigned(Loaded_From)
-          then
-            fnd:=SearchPathList(Loaded_From.LocalUnitSearchPath);
-          if not fnd
-          then
-            fnd:=SourceSearchPath('.');
-          if not fnd
-          then
-            fnd:=SearchPathList(LocalUnitSearchPath);
-          if not fnd
-          then
-            fnd:=SearchPathList(UnitSearchPath);
+         if not fnd then
+           fnd:=SourceSearchPath('.');
+         if (not fnd) and Assigned(Loaded_From) then
+           fnd:=SearchPathList(Loaded_From.LocalUnitSearchPath);
+         if not fnd then
+           fnd:=SearchPathList(UnitSearchPath);
 
          { try to find a file with the first 8 chars of the modulename, like
            dos }
@@ -430,7 +417,7 @@ uses
            { implementation units should not change
              the CRC PM }
            ppufile.do_crc:=hp.in_interface;
-           ppufile.putstring(hp.realname^);
+           ppufile.putstring(hp.u.realmodulename^);
            { the checksum should not affect the crc of this unit ! (PFV) }
            ppufile.do_crc:=false;
            ppufile.putlongint(longint(hp.checksum));
@@ -667,9 +654,10 @@ uses
     procedure tppumodule.readloadunit;
       var
         hs : string;
+        pu : tused_unit;
+        hp : tppumodule;
         intfchecksum,
         checksum : cardinal;
-        in_interface : boolean;
       begin
         while not ppufile.endofentry do
          begin
@@ -677,8 +665,14 @@ uses
            checksum:=cardinal(ppufile.getlongint);
            intfchecksum:=cardinal(ppufile.getlongint);
            in_interface:=(ppufile.getbyte<>0);
-           used_units.concat(tused_unit.create_to_load(hs,checksum,intfchecksum,in_interface));
+           { set the state of this unit before registering, this is
+             needed for a correct circular dependency check }
+           hp:=registerunit(self,hs,'');
+           pu:=addusedunit(hp,false);
+           pu.checksum:=checksum;
+           pu.interface_checksum:=intfchecksum;
          end;
+        in_interface:=false;
       end;
 
 
@@ -1012,92 +1006,80 @@ uses
     procedure tppumodule.load_usedunits;
       var
         pu           : tused_unit;
-        loaded_unit  : tmodule;
         load_refs    : boolean;
         nextmapentry : longint;
       begin
+        if current_module<>self then
+         internalerror(200212284);
         load_refs:=true;
         { init the map }
         new(map);
         fillchar(map^,sizeof(tunitmap),#0);
-{$ifdef NEWMAP}
-        map^[0]:=current_module;
-{$endif NEWMAP}
+        map^[0]:=self;
         nextmapentry:=1;
         { load the used units from interface }
-        in_implementation:=false;
+        in_interface:=true;
         pu:=tused_unit(used_units.first);
         while assigned(pu) do
          begin
-           if (not pu.loaded) and (pu.in_interface) then
+           if pu.in_interface then
             begin
-              loaded_unit:=loadunit(pu.realname^,'');
-              if compiled then
+              tppumodule(pu.u).loadppu;
+              { if this unit is compiled we can stop }
+              if state=ms_compiled then
                exit;
-              { register unit in used units }
-              pu.u:=loaded_unit;
-              pu.loaded:=true;
-              { doubles are not important for that list PM }
-              pu.u.dependent_units.concat(tdependent_unit.create(self));
+              { add this unit to the dependencies }
+              pu.u.adddependency(self);
               { need to recompile the current unit ? }
-              if loaded_unit.crc<>pu.checksum then
+              if pu.u.crc<>pu.checksum then
                begin
-                 Message2(unit_u_recompile_crc_change,realmodulename^,pu.realname^);
+                 Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^);
                  recompile_reason:=rr_crcchanged;
                  do_compile:=true;
                  dispose(map);
                  map:=nil;
                  exit;
                end;
-            { setup the map entry for deref }
-{$ifndef NEWMAP}
-              map^[nextmapentry]:=loaded_unit.globalsymtable;
-{$else NEWMAP}
-              map^[nextmapentry]:=loaded_unit;
-{$endif NEWMAP}
+              { setup the map entry for deref }
+              map^[nextmapentry]:=pu.u;
               inc(nextmapentry);
               if nextmapentry>maxunits then
                Message(unit_f_too_much_units);
             end;
            pu:=tused_unit(pu.next);
          end;
+
         { ok, now load the interface of this unit }
         if current_module<>self then
          internalerror(200208187);
-//        current_module:=self;
-//        SetCompileModule(current_module);
         globalsymtable:=tglobalsymtable.create(modulename^);
         tstoredsymtable(globalsymtable).ppuload(ppufile);
+
         { now only read the implementation uses }
-        in_implementation:=true;
+        in_interface:=false;
         pu:=tused_unit(used_units.first);
         while assigned(pu) do
          begin
-           if (not pu.loaded) and (not pu.in_interface) then
+           if (not pu.in_interface) then
             begin
-              loaded_unit:=loadunit(pu.realname^,'');
-              if compiled then
+              tppumodule(pu.u).loadppu;
+              { if this unit is compiled we can stop }
+              if state=ms_compiled then
                exit;
-            { register unit in used units }
-              pu.u:=loaded_unit;
-              pu.loaded:=true;
-            { need to recompile the current unit ? }
-              if (loaded_unit.interface_crc<>pu.interface_checksum) {and
-                 not(current_module.in_second_compile) } then
+              { add this unit to the dependencies }
+              pu.u.adddependency(self);
+              { need to recompile the current unit ? }
+              if (pu.u.interface_crc<>pu.interface_checksum) then
                 begin
-                  Message2(unit_u_recompile_crc_change,realmodulename^,pu.realname^+' {impl}');
+                  Message2(unit_u_recompile_crc_change,realmodulename^,pu.u.realmodulename^+' {impl}');
                   recompile_reason:=rr_crcchanged;
                   do_compile:=true;
                   dispose(map);
                   map:=nil;
                   exit;
                 end;
-            { setup the map entry for deref }
-{$ifndef NEWMAP}
-              map^[nextmapentry]:=loaded_unit.globalsymtable;
-{$else NEWMAP}
-              map^[nextmapentry]:=loaded_unit;
-{$endif NEWMAP}
+              { setup the map entry for deref }
+              map^[nextmapentry]:=pu.u;
               inc(nextmapentry);
               if nextmapentry>maxunits then
                Message(unit_f_too_much_units);
@@ -1113,9 +1095,9 @@ uses
          begin
            if current_module<>self then
             internalerror(200208188);
-//           current_module:=self;
            load_symtable_refs;
          end;
+
         { remove the map, it's not needed anymore }
         dispose(map);
         map:=nil;
@@ -1123,213 +1105,238 @@ uses
 
 
     procedure tppumodule.loadppu;
+      const
+        ImplIntf : array[boolean] of string[15]=('implementation','interface');
       var
-        name : string;
+        second_time : boolean;
+        hp,
+        old_current_module : tmodule;
       begin
-        { load interface section }
-          if not do_compile then
-           load_interface;
-        { only load units when we don't recompile }
-          if not do_compile then
-           load_usedunits;
-        { recompile if set }
-          if do_compile then
-           begin
-           { we don't need the ppufile anymore }
-             if assigned(ppufile) then
-              begin
-                ppufile.free;
-                ppufile:=nil;
-              end;
+        old_current_module:=current_module;
+        Message3(unit_u_load_unit,old_current_module.modulename^,
+                 ImplIntf[old_current_module.in_interface],
+                 modulename^);
+        { check if the globalsymtable is already available, but
+          we must reload when the do_reload flag is set }
+        if do_reload then
+         begin
+           Comment(V_Used,'Forced reloading');
+           do_reload:=false;
+         end
+        else
+         begin
+           if assigned(globalsymtable) then
+            exit;
+         end;
+        { reset }
+        second_time:=false;
+        current_module:=self;
+        SetCompileModule(current_module);
+
+        { we are loading a new module, save the state of the scanner
+          and reset scanner+module }
+        if assigned(current_scanner) then
+          current_scanner.tempcloseinputfile;
+        current_scanner:=nil;
+
+        { loading the unit for a second time? }
+        if state=ms_registered then
+         state:=ms_load
+        else
+         begin
+           { try to load the unit a second time first }
+           Message1(unit_u_second_load_unit,modulename^);
+           Comment(V_Used,'Previous state '+modulename^+': '+ModuleStateStr[state]);
+           { Flag modules to reload }
+           flagdependent(old_current_module);
+           { Reset the module }
+           reset;
+           if state=ms_compile then
+             begin
+               Comment(V_Used,'Already compiling '+modulename^+' setting second compile');
+               state:=ms_second_compile;
+               do_compile:=true;
+             end
+           else
+             state:=ms_second_load;
+           second_time:=true;
+         end;
+
+        { close old_current_ppu on system that are
+          short on file handles like DOS PM }
+{$ifdef SHORT_ON_FILE_HANDLES}
+        if old_current_module.is_unit and
+           assigned(tppumodule(old_current_module).ppufile) then
+          tppumodule(old_current_module).ppufile.tempclose;
+{$endif SHORT_ON_FILE_HANDLES}
+
+        { try to opening ppu, skip this when we already
+          know that we need to compile the unit }
+        if not do_compile then
+         begin
+           Comment(V_Used,'Loading module '+modulename^);
+           search_unit(false,false);
+           if not do_compile then
+            begin
+              load_interface;
+              if not do_compile then
+               begin
+                 load_usedunits;
+                 if not do_compile then
+                   Comment(V_Used,'Finished loading module '+modulename^);
+               end;
+            end;
+           { PPU is not needed anymore }
+           if assigned(ppufile) then
+            begin
+               ppufile.closefile;
+               ppufile.free;
+               ppufile:=nil;
+            end;
+         end;
+
+        { Do we need to recompile the unit }
+        if do_compile then
+         begin
            { recompile the unit or give a fatal error if sources not available }
-             if not(sources_avail) and
-                not(sources_checked) then
-               if (not search_unit(modulename^,'',true))
-                  and (length(modulename^)>8) then
-                 search_unit(copy(modulename^,1,8),'',true);
-             if not(sources_avail) then
+           if not(sources_avail) then
+            begin
+              if (not search_unit(true,false)) and
+                 (length(modulename^)>8) then
+                search_unit(true,true);
+              if not(sources_avail) then
                begin
-                  if recompile_reason=rr_noppu then
-                    Message1(unit_f_cant_find_ppu,modulename^)
-                  else
-                    Message1(unit_f_cant_compile_unit,modulename^);
-               end
-             else
-              begin
-                if in_compile then
-                  begin
-                    in_second_compile:=true;
-                    Message1(parser_d_compiling_second_time,modulename^);
-                  end;
-                name:=mainsource^;
-                { compile this module }
-                compile(name);
-                in_second_compile:=false;
-              end;
-           end;
-         if assigned(ppufile) then
-           begin
-              ppufile.closefile;
-              ppufile.free;
-              ppufile:=nil;
-           end;
-        end;
+                 if recompile_reason=rr_noppu then
+                   Message1(unit_f_cant_find_ppu,modulename^)
+                 else
+                   Message1(unit_f_cant_compile_unit,modulename^);
+               end;
+            end;
+           { Flag modules to reload }
+           flagdependent(old_current_module);
+           { Reset the module }
+           reset;
+           { compile this module }
+           if not(state in [ms_compile,ms_second_compile]) then
+             state:=ms_compile;
+           compile(mainsource^);
+         end;
+
+        { set compiled flag }
+        if current_module<>self then
+          internalerror(200212282);
+        state:=ms_compiled;
+
+        if in_interface then
+          internalerror(200212283);
+
+        { for a second_time recompile reload all dependent units,
+          for a first time compile register the unit _once_ }
+        if second_time then
+         begin
+           { now reload all dependent units }
+           hp:=tmodule(loaded_units.first);
+           while assigned(hp) do
+            begin
+              if hp.do_reload then
+                tppumodule(hp).loadppu;
+              hp:=tmodule(hp.next);
+            end;
+         end
+        else
+         usedunits.concat(tused_unit.create(self,true,false));
+
+        { reopen the old module }
+{$ifdef SHORT_ON_FILE_HANDLES}
+        if old_current_module.is_unit and
+           assigned(tppumodule(old_current_module).ppufile) then
+          tppumodule(old_current_module).ppufile.tempopen;
+{$endif SHORT_ON_FILE_HANDLES}
+
+        { we are back, restore current_module and current_scanner }
+        current_module:=old_current_module;
+        current_scanner:=tscannerfile(current_module.scanner);
+        if assigned(current_scanner) then
+          current_scanner.tempopeninputfile;
+        SetCompileModule(current_module);
+      end;
 
 
 {*****************************************************************************
-                                  LoadUnit
+                               RegisterUnit
 *****************************************************************************}
 
-    function loadunit(const s : stringid;const fn:string) : tmodule;
-      const
-        ImplIntf : array[boolean] of string[15]=('interface','implementation');
+
+    function registerunit(callermodule:tmodule;const s : stringid;const fn:string) : tppumodule;
       var
-        st : tglobalsymtable;
-        second_time : boolean;
-        old_current_module,hp2 : tmodule;
-        hp : tppumodule;
-        scanner : tscannerfile;
-        dummy : tmodule;
         ups   : stringid;
+        hp    : tppumodule;
+        hp2,
+        shortnamehp : tmodule;
       begin
-         old_current_module:=current_module;
-         { we are loading a new module, save the state of the scanner
-           and reset scanner+module }
-         if assigned(current_scanner) then
-           current_scanner.tempcloseinputfile;
-         current_scanner:=nil;
-         current_module:=nil;
-         { Info }
-         Message3(unit_u_load_unit,old_current_module.modulename^,ImplIntf[old_current_module.in_implementation],s);
-         ups:=upper(s);
-         { unit not found }
-         st:=nil;
-         dummy:=nil;
-         { search all loaded units }
-         hp:=tppumodule(loaded_units.first);
-         while assigned(hp) do
-           begin
-              if hp.modulename^=ups then
-                begin
-                   { forced to reload ? }
-                   if hp.do_reload then
-                    begin
-                      hp.do_reload:=false;
-                      break;
-                    end;
-                   { only check for units. The main program is also
-                     as a unit in the loaded_units list. We simply need
-                     to ignore this entry (PFV) }
-                   if hp.is_unit then
-                    begin
-                      { the unit is already registered   }
-                      { and this means that the unit     }
-                      { is already compiled              }
-                      { else there is a cyclic unit use  }
-                      if assigned(hp.globalsymtable) then
-                        st:=tglobalsymtable(hp.globalsymtable)
-                      else
-                       begin
-                         { both units in interface ? }
-                         if (not old_current_module.in_implementation) and
-                            (not hp.in_implementation) then
-                          begin
-                            { check for a cycle }
-                            hp2:=old_current_module.loaded_from;
-                            while assigned(hp2) and (hp2<>hp) do
-                             begin
-                               if hp2.in_implementation then
-                                 hp2:=nil
-                               else
-                                 hp2:=hp2.loaded_from;
-                             end;
-                            if assigned(hp2) then
-                              Message2(unit_f_circular_unit_reference,old_current_module.modulename^,hp.modulename^);
-                          end;
-                       end;
-                      break;
-                    end;
-                end
-              else if copy(hp.modulename^,1,8)=ups then
-                dummy:=hp;
-              { the next unit }
-              hp:=tppumodule(hp.next);
-           end;
-         if assigned(dummy) and not assigned(hp) then
-           Message2(unit_w_unit_name_error,s,dummy.modulename^);
-       { the unit is not in the loaded units, we must load it first }
-         if (not assigned(st)) then
-          begin
-            if assigned(hp) then
-             begin
-               current_module:=hp;
-               { try to load the unit a second time first }
-               Message1(unit_u_second_load_unit,current_module.modulename^);
-               second_time:=true;
-               current_module.in_second_load:=true;
-               { remove the old unit }
-               loaded_units.remove(current_module);
-               current_module.reset;
-               { try to reopen ppu }
-               tppumodule(current_module).search_unit(s,fn,false);
-             end
-            else
-          { generates a new unit info record }
-             begin
-               current_module:=tppumodule.create(old_current_module,s,fn,true);
-               second_time:=false;
-             end;
-            { close old_current_ppu on system that are
-              short on file handles like DOS PM }
-{$ifdef SHORT_ON_FILE_HANDLES}
-            if old_current_module.is_unit and
-               assigned(tppumodule(old_current_module).ppufile) then
-              tppumodule(old_current_module).ppufile.tempclose;
-{$endif SHORT_ON_FILE_HANDLES}
-          { now we can register the unit }
-            current_module.loaded_from:=old_current_module;
-            loaded_units.insert(current_module);
-          { now realy load the ppu }
-            tppumodule(current_module).loadppu;
-          { set compiled flag }
-            current_module.compiled:=true;
-          { load return pointer }
-            hp:=tppumodule(current_module);
-          { for a second_time recompile reload all dependent units,
-            for a first time compile register the unit _once_ }
-            if second_time then
-             begin
-               { now reload all dependent units }
-               hp2:=tmodule(loaded_units.first);
-               while assigned(hp2) do
-                begin
-                  if hp2.do_reload then
-                   dummy:=loadunit(hp2.modulename^,'');
-                  hp2:=tmodule(hp2.next);
-                end;
-             end
-            else
-             usedunits.concat(tused_unit.create(current_module,true));
-          end;
-         { set the old module }
-{$ifdef SHORT_ON_FILE_HANDLES}
-         if old_current_module.is_unit and
-            assigned(tppumodule(old_current_module).ppufile) then
-           tppumodule(old_current_module).ppufile.tempopen;
-{$endif SHORT_ON_FILE_HANDLES}
-         { we are back, restore current_module and current_scanner }
-         current_module:=old_current_module;
-         current_scanner:=tscannerfile(current_module.scanner);
-         if assigned(current_scanner) then
-           current_scanner.tempopeninputfile;
-         SetCompileModule(current_module);
-         loadunit:=hp;
+        { Info }
+        ups:=upper(s);
+        { search all loaded units }
+        shortnamehp:=nil;
+        hp:=tppumodule(loaded_units.first);
+        while assigned(hp) do
+         begin
+           if hp.modulename^=ups then
+            begin
+              { only check for units. The main program is also
+                as a unit in the loaded_units list. We simply need
+                to ignore this entry (PFV) }
+              if hp.is_unit then
+               begin
+                 { both units in interface ? }
+                 if callermodule.in_interface and
+                    hp.in_interface then
+                  begin
+                    { check for a cycle }
+                    hp2:=callermodule.loaded_from;
+                    while assigned(hp2) and (hp2<>hp) do
+                     begin
+                       if hp2.in_interface then
+                         hp2:=hp2.loaded_from
+                       else
+                         hp2:=nil;
+                     end;
+                    if assigned(hp2) then
+                      Message2(unit_f_circular_unit_reference,callermodule.modulename^,hp.modulename^);
+                  end;
+                 break;
+               end;
+            end
+           else
+            if copy(hp.modulename^,1,8)=ups then
+             shortnamehp:=hp;
+           { the next unit }
+           hp:=tppumodule(hp.next);
+         end;
+        if assigned(shortnamehp) and not assigned(hp) then
+          Message2(unit_w_unit_name_error,s,shortnamehp.modulename^);
+        { the unit is not in the loaded units,
+          we create an entry and register the unit }
+        if not assigned(hp) then
+         begin
+           Comment(V_Used,'Registering new unit '+Upper(s));
+           hp:=tppumodule.create(callermodule,s,fn,true);
+           hp.loaded_from:=callermodule;
+           loaded_units.insert(hp);
+         end;
+        { return }
+        registerunit:=hp;
       end;
 
 end.
 {
   $Log$
-  Revision 1.28  2002-12-06 16:56:57  peter
+  Revision 1.29  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.28  2002/12/06 16:56:57  peter
     * only compile cs_fp_emulation support when cpufpuemu is defined
     * define cpufpuemu for m68k only
 

+ 12 - 7
compiler/parser.pas

@@ -39,7 +39,7 @@ implementation
       cutils,cclasses,
       globtype,version,tokens,systems,globals,verbose,
       symbase,symtable,symdef,symsym,
-      fmodule,fppu,
+      finput,fmodule,fppu,
       aasmbase,aasmtai,
       cgbase,
       script,gendef,
@@ -384,13 +384,14 @@ implementation
          aktmaxfpuregisters:=-1;
          fillchar(overloaded_operators,sizeof(toverloaded_operators),0);
        { reset the unit or create a new program }
-         if assigned(current_module) then
-          current_module.reset
-         else
+         if not assigned(current_module) then
           begin
             current_module:=tppumodule.create(nil,filename,'',false);
             main_module:=current_module;
+            current_module.state:=ms_compile;
           end;
+         if not(current_module.state in [ms_compile,ms_second_compile]) then
+           internalerror(200212281);
 
          { a unit compiled at command line must be inside the loaded_unit list }
          if (compile_level=1) then
@@ -398,9 +399,8 @@ implementation
 
          { Set the module to use for verbose }
          SetCompileModule(current_module);
-
          compiled_module:=current_module;
-         current_module.in_compile:=true;
+
        { Load current state from the init values }
          aktlocalswitches:=initlocalswitches;
          aktmoduleswitches:=initmoduleswitches;
@@ -621,7 +621,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.47  2002-12-24 23:32:19  peter
+  Revision 1.48  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.47  2002/12/24 23:32:19  peter
     * fixed crash when old_compiled_module was nil
 
   Revision 1.46  2002/11/20 12:36:24  mazen

+ 7 - 2
compiler/pdecl.pas

@@ -509,7 +509,7 @@ implementation
 
               { generate persistent init/final tables when it's declared in the interface so it can
                 be reused in other used }
-              if (not current_module.in_implementation) and
+              if current_module.in_interface and
                  ((is_class(tt.def) and
                    tobjectdef(tt.def).members_need_inittable) or
                   tt.def.needs_inittable) then
@@ -627,7 +627,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.62  2002-12-05 19:27:40  carl
+  Revision 1.63  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.62  2002/12/05 19:27:40  carl
     - remove lower in hint
 
   Revision 1.61  2002/11/25 18:43:32  carl

+ 108 - 127
compiler/pmodules.pas

@@ -414,9 +414,26 @@ implementation
 
 
     procedure loaddefaultunits;
-      var
-        hp : tmodule;
-        unitsym : tunitsym;
+
+        procedure AddUnit(const s:string);
+        var
+          hp : tppumodule;
+          unitsym : tunitsym;
+        begin
+          { load unit }
+          hp:=registerunit(current_module,s,'');
+          hp.loadppu;
+          hp.adddependency(current_module);
+          current_module.addusedunit(hp,false);
+          { add to symtable stack }
+          tsymtable(hp.globalsymtable).next:=symtablestack;
+          symtablestack:=hp.globalsymtable;
+          { insert unitsym }
+          unitsym:=tunitsym.create(s,hp.globalsymtable);
+          inc(unitsym.refs);
+          refsymtable.insert(unitsym);
+        end;
+
       begin
       { are we compiling the system unit? }
         if (cs_compilesystem in aktmoduleswitches) then
@@ -426,100 +443,40 @@ implementation
          { we don't need to reset anything, it's already done in parser.pas }
            exit;
          end;
-     { insert the system unit, it is allways the first }
-        hp:=loadunit('System','');
-        systemunit:=tglobalsymtable(hp.globalsymtable);
-        { it's always the first unit }
-        systemunit.next:=nil;
-        symtablestack:=systemunit;
-        { add to the used units }
-        current_module.used_units.concat(tused_unit.create(hp,true));
-        unitsym:=tunitsym.create('System',systemunit);
-        inc(unitsym.refs);
-        refsymtable.insert(unitsym);
+        { insert the system unit, it is allways the first }
+        Symtablestack:=nil;
+        AddUnit('System');
+        SystemUnit:=TGlobalSymtable(Symtablestack);
         { read default constant definitions }
         make_ref:=false;
         readconstdefs;
         make_ref:=true;
 {$ifdef cpufpemu}
-      { Floating point emulation unit? }
+        { Floating point emulation unit? }
         if (cs_fp_emulation in aktmoduleswitches) then
-         begin
-           hp:=loadunit('softfpu','');
-           tsymtable(hp.globalsymtable).next:=symtablestack;
-           symtablestack:=hp.globalsymtable;
-           { add to the used units }
-           current_module.used_units.concat(tused_unit.create(hp,true));
-           unitsym:=tunitsym.create('Softfpu',hp.globalsymtable);
-           inc(unitsym.refs);
-           refsymtable.insert(unitsym);
-         end;
+          AddUnit('SoftFpu');
 {$endif cpufpemu}
-      { Thread support unit? }
+        { Thread support unit? }
         if (cs_threading in aktmoduleswitches) then
-         begin
-           hp:=loadunit('systhrds','');
-           tsymtable(hp.globalsymtable).next:=symtablestack;
-           symtablestack:=hp.globalsymtable;
-           { add to the used units }
-           current_module.used_units.concat(tused_unit.create(hp,true));
-           unitsym:=tunitsym.create('Threads',hp.globalsymtable);
-           inc(unitsym.refs);
-           refsymtable.insert(unitsym);
-         end;
-      { Objpas unit? }
+          AddUnit('SysThrds');
+        { Objpas unit? }
         if m_objpas in aktmodeswitches then
-         begin
-           hp:=loadunit('ObjPas','');
-           tsymtable(hp.globalsymtable).next:=symtablestack;
-           symtablestack:=hp.globalsymtable;
-           { add to the used units }
-           current_module.used_units.concat(tused_unit.create(hp,true));
-           unitsym:=tunitsym.create('ObjPas',hp.globalsymtable);
-           inc(unitsym.refs);
-           refsymtable.insert(unitsym);
-         end;
-      { Profile unit? Needed for go32v2 only }
-        if (cs_profile in aktmoduleswitches) and (target_info.system=system_i386_go32v2) then
-         begin
-           hp:=loadunit('Profile','');
-           tsymtable(hp.globalsymtable).next:=symtablestack;
-           symtablestack:=hp.globalsymtable;
-           { add to the used units }
-           current_module.used_units.concat(tused_unit.create(hp,true));
-           unitsym:=tunitsym.create('Profile',hp.globalsymtable);
-           inc(unitsym.refs);
-           refsymtable.insert(unitsym);
-         end;
-      { Units only required for main module }
+          AddUnit('ObjPas');
+        { Profile unit? Needed for go32v2 only }
+        if (cs_profile in aktmoduleswitches) and
+           (target_info.system=system_i386_go32v2) then
+          AddUnit('Profile');
+        { Units only required for main module }
         if not(current_module.is_unit) then
          begin
            { Heaptrc unit }
            if (cs_gdb_heaptrc in aktglobalswitches) then
-            begin
-              hp:=loadunit('HeapTrc','');
-              tsymtable(hp.globalsymtable).next:=symtablestack;
-              symtablestack:=hp.globalsymtable;
-              { add to the used units }
-              current_module.used_units.concat(tused_unit.create(hp,true));
-              unitsym:=tunitsym.create('HeapTrc',hp.globalsymtable);
-              inc(unitsym.refs);
-              refsymtable.insert(unitsym);
-            end;
+             AddUnit('HeapTrc');
            { Lineinfo unit }
            if (cs_gdb_lineinfo in aktglobalswitches) then
-            begin
-              hp:=loadunit('LineInfo','');
-              tsymtable(hp.globalsymtable).next:=symtablestack;
-              symtablestack:=hp.globalsymtable;
-              { add to the used units }
-              current_module.used_units.concat(tused_unit.create(hp,true));
-              unitsym:=tunitsym.create('LineInfo',hp.globalsymtable);
-              inc(unitsym.refs);
-              refsymtable.insert(unitsym);
-            end;
+             AddUnit('LineInfo');
          end;
-      { save default symtablestack }
+        { save default symtablestack }
         defaultsymtablestack:=symtablestack;
       end;
 
@@ -528,10 +485,9 @@ implementation
       var
          s,sorg : stringid;
          fn     : string;
-         pu,
-         hp : tused_unit;
-         hp2 : tmodule;
-         hp3 : tsymtable;
+         pu     : tused_unit;
+         hp2    : tmodule;
+         hp3    : tsymtable;
          oldprocsym:tprocsym;
          oldprocdef:tprocdef;
          unitsym : tunitsym;
@@ -561,26 +517,17 @@ implementation
            pu:=tused_unit(current_module.used_units.first);
            while assigned(pu) do
             begin
-              if (pu.name^=s) then
+              if (pu.u.modulename^=s) then
                break;
               pu:=tused_unit(pu.next);
             end;
          { avoid uses of itself }
            if not assigned(pu) and (s<>current_module.modulename^) then
             begin
-            { load the unit }
-              hp2:=loadunit(sorg,fn);
-            { the current module uses the unit hp2 }
-              current_module.used_units.concat(tused_unit.create(hp2,not current_module.in_implementation));
-              tused_unit(current_module.used_units.last).in_uses:=true;
-              if current_module.compiled then
-                exit;
-              unitsym:=tunitsym.create(sorg,hp2.globalsymtable);
-              { never claim about unused unit if
-                there is init or finalize code  PM }
-              if (hp2.flags and (uf_init or uf_finalize))<>0 then
-                inc(unitsym.refs);
-              refsymtable.insert(unitsym);
+              { register the unit }
+              hp2:=registerunit(current_module,sorg,fn);
+              { the current module uses the unit hp2 }
+              current_module.addusedunit(hp2,true);
             end
            else
             Message1(sym_e_duplicate_id,s);
@@ -594,44 +541,69 @@ implementation
          until false;
          consume(_SEMICOLON);
 
-         { set the symtable to systemunit so it gets reorderd correctly }
-         symtablestack:=defaultsymtablestack;
+         { Load the units }
+         pu:=tused_unit(current_module.used_units.first);
+         while assigned(pu) do
+          begin
+            if pu.in_uses then
+             begin
+               tppumodule(pu.u).loadppu;
+               { is our module compiled? then we can stop }
+               if current_module.state=ms_compiled then
+                exit;
+               { add this unit to the dependencies }
+               pu.u.adddependency(current_module);
+               pu.checksum:=pu.u.crc;
+               pu.interface_checksum:=pu.u.interface_crc;
+             end;
+            pu:=tused_unit(pu.next);
+          end;
 
-         { now insert the units in the symtablestack }
-         hp:=tused_unit(current_module.used_units.first);
-         while assigned(hp) do
+         { set the symtable to systemunit so it gets reorderd correctly,
+           then insert the units in the symtablestack }
+         pu:=tused_unit(current_module.used_units.first);
+         symtablestack:=defaultsymtablestack;
+         while assigned(pu) do
            begin
 {$IfDef GDB}
               if (cs_debuginfo in aktmoduleswitches) and
                  (cs_gdb_dbx in aktglobalswitches) and
-                not hp.is_stab_written then
+                not pu.is_stab_written then
                 begin
-                   tglobalsymtable(hp.u.globalsymtable).concattypestabto(debuglist);
-                   hp.is_stab_written:=true;
-                   hp.unitid:=tsymtable(hp.u.globalsymtable).unitid;
+                   tglobalsymtable(pu.u.globalsymtable).concattypestabto(debuglist);
+                   pu.is_stab_written:=true;
+                   pu.unitid:=tsymtable(pu.u.globalsymtable).unitid;
                 end;
 {$EndIf GDB}
-              if hp.in_uses then
+              if pu.in_uses then
                 begin
+                   { Create unitsym }
+                   unitsym:=tunitsym.create(pu.u.realmodulename^,pu.u.globalsymtable);
+                   { never claim about unused unit if
+                     there is init or finalize code  PM }
+                   if (hp2.flags and (uf_init or uf_finalize))<>0 then
+                     inc(unitsym.refs);
+                   refsymtable.insert(unitsym);
+                   { Reinsert in symtablestack }
                    hp3:=symtablestack;
                    while assigned(hp3) do
                      begin
                         { insert units only once ! }
-                        if hp.u.globalsymtable=hp3 then
+                        if pu.u.globalsymtable=hp3 then
                           break;
                         hp3:=hp3.next;
                         { unit isn't inserted }
                         if hp3=nil then
                           begin
-                             tsymtable(hp.u.globalsymtable).next:=symtablestack;
-                             symtablestack:=tsymtable(hp.u.globalsymtable);
+                             tsymtable(pu.u.globalsymtable).next:=symtablestack;
+                             symtablestack:=tsymtable(pu.u.globalsymtable);
 {$ifdef DEBUG}
                              test_symtablestack;
 {$endif DEBUG}
                           end;
                      end;
                 end;
-              hp:=tused_unit(hp.next);
+              pu:=tused_unit(pu.next);
            end;
           aktprocsym:=oldprocsym;
           aktprocdef:=oldprocdef;
@@ -658,7 +630,7 @@ implementation
                 end;
               hp:=tused_unit(hp.next);
            end;
-         if current_module.in_implementation and
+         if (not current_module.in_interface) and
             assigned(current_module.localsymtable) then
            begin
               { all types }
@@ -830,7 +802,8 @@ implementation
          { handle the global switches }
          setupglobalswitches;
 
-         Message1(unit_u_start_parse_interface,current_module.realmodulename^);
+         Comment(V_Used,'Loading interface units from '+current_module.modulename^);
+//         Message1(unit_u_start_parse_interface,current_module.modulename^);
 
          { update status }
          status.currentmodule:=current_module.realmodulename^;
@@ -868,7 +841,7 @@ implementation
                 begin
                    loadunits;
                    { has it been compiled at a higher level ?}
-                   if current_module.compiled then
+                   if current_module.state=ms_compiled then
                      begin
                         { this unit symtable is obsolete }
                         { dispose(unitst,done);
@@ -903,7 +876,8 @@ implementation
          current_module.numberunits;
 
          { ... parse the declarations }
-         Message1(parser_u_parsing_interface,current_module.realmodulename^);
+         Comment(V_Used,'Parsing interface of '+current_module.modulename^);
+//         Message1(parser_u_parsing_interface,current_module.realmodulename^);
          read_interface_declarations;
 
          { leave when we got an error }
@@ -926,8 +900,10 @@ implementation
 
          { Parse the implementation section }
          consume(_IMPLEMENTATION);
-         current_module.in_implementation:=true;
-         Message1(unit_u_start_parse_implementation,current_module.modulename^);
+         current_module.in_interface:=false;
+
+         Comment(V_Used,'Loading implementation units from '+current_module.modulename^);
+//         Message1(unit_u_start_parse_implementation,current_module.modulename^);
 
          parse_only:=false;
 
@@ -945,7 +921,7 @@ implementation
          { Read the implementation units }
          parse_implementation_uses(unitst);
 
-         if current_module.compiled then
+         if current_module.state=ms_compiled then
            begin
               RestoreUnitSyms;
               exit;
@@ -982,7 +958,10 @@ implementation
          allow_special:=false;
 {$endif Splitheap}
 
-         Message1(parser_u_parsing_implementation,current_module.realmodulename^);
+         Comment(V_Used,'Parsing implementation of '+current_module.modulename^);
+         if current_module.in_interface then
+           internalerror(200212285);
+//         Message1(parser_u_parsing_implementation,current_module.modulename^);
 
          { Compile the unit }
          codegen_newprocedure;
@@ -1098,7 +1077,6 @@ implementation
              tstoredsymtable(symtablestack).unchain_overloaded;
            end;
 
-         current_module.in_implementation:=false;
 {$ifdef GDB}
          tglobalsymtable(symtablestack).is_stab_written:=false;
 {$endif GDB}
@@ -1120,8 +1098,7 @@ implementation
          if is_assembler_generated then
            insertobjectfile
          else
-           if not (current_module.uses_imports) then
-             current_module.flags:=current_module.flags or uf_no_link;
+           current_module.flags:=current_module.flags or uf_no_link;
 
          if cs_local_browser in aktmoduleswitches then
            current_module.localsymtable:=refsymtable;
@@ -1176,6 +1153,8 @@ implementation
             status.skip_error:=true;
             exit;
           end;
+
+        Comment(V_Used,'Finished compiling module '+current_module.modulename^);
       end;
 
 
@@ -1255,7 +1234,7 @@ implementation
          setupglobalswitches;
 
          { set implementation flag }
-         current_module.in_implementation:=true;
+         current_module.in_interface:=false;
 
          { insert after the unit symbol tables the static symbol table }
          { of the program                                             }
@@ -1456,8 +1435,10 @@ implementation
 end.
 {
   $Log$
-  Revision 1.88  2002-12-27 19:09:33  hajny
-    * another (hopefully final ;-) ) fix for not linked import libraries for units with no code
+  Revision 1.89  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
 
   Revision 1.87  2002/12/24 23:32:56  peter
     * Use FixFilename for specified unit sourcefile in uses

+ 7 - 2
compiler/psub.pas

@@ -539,7 +539,7 @@ implementation
          else
           begin
             pdflags:=pd_body;
-            if current_module.in_implementation then
+            if (not current_module.in_interface) then
              pdflags:=pdflags or pd_implemen;
             if (not current_module.is_unit) or (cs_create_smart in aktmoduleswitches) then
              pdflags:=pdflags or pd_global;
@@ -818,7 +818,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.82  2002-12-25 01:26:56  peter
+  Revision 1.83  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.82  2002/12/25 01:26:56  peter
     * duplicate procsym-unitsym fix
 
   Revision 1.81  2002/12/15 13:37:15  peter

+ 7 - 2
compiler/scanner.pas

@@ -939,7 +939,7 @@ implementation
     destructor tscannerfile.destroy;
       begin
         if assigned(current_module) and
-           (not current_module.in_second_load) and
+           (current_module.state<>ms_second_load) and
            (status.errorcount=0) then
           checkpreprocstack
         else
@@ -2801,7 +2801,12 @@ exit_label:
 end.
 {
   $Log$
-  Revision 1.55  2002-12-27 18:05:58  peter
+  Revision 1.56  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.55  2002/12/27 18:05:58  peter
     * use gettoken to get filename for include
 
   Revision 1.54  2002/12/27 16:45:50  peter

+ 6 - 2
compiler/symconst.pas

@@ -317,7 +317,6 @@ const
 const
   { relevant options for assigning a proc or a procvar to a procvar }
   po_compatibility_options = [
-    po_classmethod,
     po_staticmethod,
     po_methodpointer,
     po_containsself,
@@ -339,7 +338,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.39  2002-12-15 11:26:02  peter
+  Revision 1.40  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.39  2002/12/15 11:26:02  peter
     * ignore vs_hidden parameters when choosing overloaded proc
 
   Revision 1.38  2002/12/05 14:44:38  florian

+ 7 - 12
compiler/symtable.pas

@@ -1751,11 +1751,6 @@ implementation
 {$endif GDB}
 
          symtablelevel:=0;
-{$ifndef NEWMAP}
-         current_module.map^[0]:=self;
-{$else NEWMAP}
-         current_module.globalsymtable:=self;
-{$endif NEWMAP}
 
          next:=symtablestack;
          symtablestack:=self;
@@ -1768,12 +1763,7 @@ implementation
          { restore symtablestack }
          symtablestack:=next;
 
-{$ifdef NEWMAP}
-         { necessary for dependencies }
-         current_module.globalsymtable:=nil;
-{$endif NEWMAP}
-
-        { read dbx count }
+         { read dbx count }
 {$ifdef GDB}
         if (current_module.flags and uf_has_dbx)<>0 then
          begin
@@ -2360,7 +2350,12 @@ implementation
 end.
 {
   $Log$
-  Revision 1.88  2002-12-27 18:07:45  peter
+  Revision 1.89  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.88  2002/12/27 18:07:45  peter
     * fix crashes when searching symbols
 
   Revision 1.87  2002/12/25 01:26:56  peter

+ 23 - 11
compiler/symtype.pas

@@ -320,9 +320,16 @@ implementation
          begin
            resolvesym(pointer(sym));
            setsym(sym);
+           if not assigned(def) then
+            internalerror(200212271);
          end
         else
-         resolvedef(pointer(def));
+         if assigned(def) then
+          begin
+            resolvedef(pointer(def));
+            if not assigned(def) then
+             internalerror(200212272);
+          end;
       end;
 
 {****************************************************************************
@@ -455,6 +462,7 @@ implementation
       var
         hp : tderef;
         pd : tdef;
+        pm : tmodule;
       begin
         st:=nil;
         idx:=0;
@@ -478,39 +486,38 @@ implementation
                end;
              derefunit :
                begin
-{$ifdef NEWMAP}
-                 st:=tsymtable(current_module.map^[p.index]^.globalsymtable);
-{$else NEWMAP}
-                 st:=tsymtable(current_module.map^[p.index]);
-{$endif NEWMAP}
+                 pm:=current_module.map^[p.index];
+                 if not assigned(pm) then
+                  internalerror(200212273);
+                 st:=pm.globalsymtable;
                end;
              derefrecord :
                begin
                  pd:=tdef(st.getdefnr(p.index));
                  st:=pd.getsymtable(gs_record);
                  if not assigned(st) then
-                  internalerror(556658);
+                  internalerror(200212274);
                end;
              dereflocal :
                begin
                  pd:=tdef(st.getdefnr(p.index));
                  st:=pd.getsymtable(gs_local);
                  if not assigned(st) then
-                  internalerror(556658);
+                  internalerror(200212275);
                end;
              derefpara :
                begin
                  pd:=tdef(st.getdefnr(p.index));
                  st:=pd.getsymtable(gs_para);
                  if not assigned(st) then
-                  internalerror(556658);
+                  internalerror(200212276);
                end;
              derefindex :
                begin
                  idx:=p.index;
                end;
              else
-               internalerror(556658);
+               internalerror(200212277);
            end;
            hp:=p;
            p:=p.next;
@@ -571,7 +578,12 @@ finalization
 end.
 {
   $Log$
-  Revision 1.22  2002-09-05 19:29:46  peter
+  Revision 1.23  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.22  2002/09/05 19:29:46  peter
     * memdebug enhancements
 
   Revision 1.21  2002/08/18 20:06:28  peter

+ 7 - 2
compiler/verbose.pas

@@ -361,7 +361,7 @@ var
            lastmoduleidx:=compiling_module.unit_index;
          end;
         if assigned(compiling_module) then
-          status.compiling_current:=compiling_module.in_compile;
+          status.compiling_current:=(compiling_module.state in [ms_compile,ms_second_compile]);
       end;
 
 
@@ -711,7 +711,12 @@ finalization
 end.
 {
   $Log$
-  Revision 1.22  2002-11-15 01:58:54  peter
+  Revision 1.23  2002-12-29 14:57:50  peter
+    * unit loading changed to first register units and load them
+      afterwards. This is needed to support uses xxx in yyy correctly
+    * unit dependency check fixed
+
+  Revision 1.22  2002/11/15 01:58:54  peter
     * merged changes from 1.0.7 up to 04-11
       - -V option for generating bug report tracing
       - more tracing for option parsing