home *** CD-ROM | disk | FTP | other *** search
/ Geek Gadgets 1 / ADE-1.bin / ade-dist / gnat-2.06-src.tgz / tar.out / fsf / gnat / ada / ali.adb < prev    next >
Text File  |  1996-09-28  |  24KB  |  892 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                                  A L I                                   --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.39 $                             --
  10. --                                                                          --
  11. --           Copyright (c) 1992,1993,1994 NYU, All Rights Reserved          --
  12. --                                                                          --
  13. -- GNAT is free software;  you can  redistribute it  and/or modify it under --
  14. -- terms of the  GNU General Public License as published  by the Free Soft- --
  15. -- ware  Foundation;  either version 2,  or (at your option) any later ver- --
  16. -- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
  17. -- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
  18. -- or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License --
  19. -- for  more details.  You should have  received  a copy of the GNU General --
  20. -- Public License  distributed with GNAT;  see file COPYING.  If not, write --
  21. -- to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. --
  22. --                                                                          --
  23. ------------------------------------------------------------------------------
  24.  
  25. with Binderr; use Binderr;
  26. with Butil;   use Butil;
  27. with Namet;   use Namet;
  28. with Opt;     use Opt;
  29. with Osint;   use Osint;
  30. with Output;  use Output;
  31.  
  32. package body ALI is
  33.  
  34.    use Ascii;
  35.    --  Make control characters visible
  36.  
  37.    --------------------
  38.    -- Initialize_ALI --
  39.    --------------------
  40.  
  41.    procedure Initialize_ALI is
  42.    begin
  43.       ALIs.Init;
  44.       Unit.Init;
  45.       Withs.Init;
  46.       Sdep.Init;
  47.    end Initialize_ALI;
  48.  
  49.    --------------
  50.    -- Read_ALI --
  51.    --------------
  52.  
  53.    procedure Read_ALI (Id : ALI_Id) is
  54.       Afile : File_Name_Type;
  55.       Text  : Text_Buffer_Ptr;
  56.  
  57.    begin
  58.       for I in ALIs.Table (Id).First_Unit .. ALIs.Table (Id).Last_Unit loop
  59.          for J in Unit.Table (I).First_With .. Unit.Table (I).Last_With loop
  60.  
  61.             Afile := Withs.Table (J).Afile;
  62.  
  63.             --  Only process if not a generic (Afile /= No_File) and if
  64.             --  file has not been processed already.
  65.  
  66.             if Afile /= No_File and then Get_Name_Table_Info (Afile) = 0 then
  67.  
  68.                Text := Read_Library_Info (Afile);
  69.                if Text = null then
  70.                   Error_Msg_Name_1 := Afile;
  71.                   Error_Msg_Name_2 := Withs.Table (J).Sfile;
  72.                   Error_Msg ("% not found, % must be compiled");
  73.                   Set_Name_Table_Info (Afile, Int (No_Unit_Id));
  74.                   return;
  75.                end if;
  76.  
  77.                Read_ALI (Scan_ALI (Afile, Text));
  78.                --  Scan and recurse
  79.             end if;
  80.          end loop;
  81.       end loop;
  82.  
  83.    end Read_ALI;
  84.  
  85.    --------------
  86.    -- Scan_ALI --
  87.    --------------
  88.  
  89.    function Scan_ALI (F : File_Name_Type; T : Text_Buffer_Ptr) return ALI_Id is
  90.       P    : Text_Ptr := T'First;
  91.       Line : Logical_Line_Number := 1;
  92.       Id   : ALI_Id;
  93.       C    : Character;
  94.  
  95.       function At_Eol return Boolean;
  96.       --  Test if at end of line
  97.  
  98.       function At_End_Of_Field return Boolean;
  99.       --  Test if at end of line, or if at blank or horizontal tab
  100.  
  101.       procedure Check_At_End_Of_Field;
  102.       --  Check if we are at end of field, fatal error if not
  103.  
  104.       procedure Checkc (C : Character);
  105.       --  Check next character is C. If so bump past it, if not fatal error
  106.  
  107.       procedure Fatal_Error;
  108.       --  Generate fatal error message for badly formatted ALI file
  109.  
  110.       function Getc return Character;
  111.       --  Get next character, bumping P past the character obtained
  112.  
  113.       function Get_Name return Name_Id;
  114.       --  Skip blanks, then scan out a name (name is left in Name_Buffer with
  115.       --  length in Name_Len, as well as being returned in Name_Id form)
  116.  
  117.       function Get_Nat return Nat;
  118.       --  Skip blanks, then scan out an unsigned integer value in Nat range
  119.  
  120.       function Get_Stamp return Time_Stamp_Type;
  121.       --  Skip blanks, then scan out a time stamp
  122.  
  123.       procedure Skip_Eol;
  124.       --  Skip past end of line (fatal error if not at end of line)
  125.  
  126.       procedure Skip_Space;
  127.       --  Skip past white space (blanks or horizontal tab)
  128.  
  129.       ------------
  130.       -- At_Eol --
  131.       ------------
  132.  
  133.       function At_Eol return Boolean is
  134.       begin
  135.          return T (P) = EOF or else T (P) = CR or else T (P) = LF;
  136.       end At_Eol;
  137.  
  138.       ---------------------
  139.       -- At_End_Of_Field --
  140.       ---------------------
  141.  
  142.       function At_End_Of_Field return Boolean is
  143.       begin
  144.          return T (P) <= ' ';
  145.       end At_End_Of_Field;
  146.  
  147.       ---------------------------
  148.       -- Check_At_End_Of_Field --
  149.       ---------------------------
  150.  
  151.       procedure Check_At_End_Of_Field is
  152.       begin
  153.          if not At_End_Of_Field then
  154.             Fatal_Error;
  155.          end if;
  156.       end Check_At_End_Of_Field;
  157.  
  158.       ------------
  159.       -- Checkc --
  160.       ------------
  161.  
  162.       procedure Checkc (C : Character) is
  163.       begin
  164.          if T (P) = C then
  165.             P := P + 1;
  166.          else
  167.             Fatal_Error;
  168.          end if;
  169.       end Checkc;
  170.  
  171.       -----------------
  172.       -- Fatal_Error --
  173.       -----------------
  174.  
  175.       procedure Fatal_Error is
  176.          Ptr1 : Text_Ptr;
  177.          Ptr2 : Text_Ptr;
  178.          Col  : Int;
  179.  
  180.          procedure Wchar (C : Character);
  181.          --  Write a single character, replacing horizontal tab by spaces
  182.  
  183.          procedure Wchar (C : Character) is
  184.          begin
  185.             if C = HT then
  186.                loop
  187.                   Wchar (' ');
  188.                   exit when Col mod 8 = 0;
  189.                end loop;
  190.  
  191.             else
  192.                Write_Char (C);
  193.                Col := Col + 1;
  194.             end if;
  195.          end Wchar;
  196.  
  197.       --  Start of processing for Fatal_Error
  198.  
  199.       begin
  200.          Write_Str ("fatal error: file ");
  201.          Write_Name (F);
  202.          Write_Str (" is incorrectly formatted");
  203.          Write_Eol;
  204.  
  205.          --  Find start of line
  206.  
  207.          Ptr1 := P;
  208.  
  209.          while Ptr1 > T'First
  210.            and then T (Ptr1 - 1) /= CR
  211.            and then T (Ptr1 - 1) /= LF
  212.          loop
  213.             Ptr1 := Ptr1 - 1;
  214.          end loop;
  215.  
  216.          Write_Int (Int (Line));
  217.          Write_Str (". ");
  218.  
  219.          if Line < 100 then
  220.             Write_Char (' ');
  221.          end if;
  222.  
  223.          if Line < 10 then
  224.             Write_Char (' ');
  225.          end if;
  226.  
  227.          Col := 0;
  228.          Ptr2 := Ptr1;
  229.  
  230.          while Ptr2 < T'Last
  231.            and then T (Ptr2) /= CR
  232.            and then T (Ptr2) /= LF
  233.          loop
  234.             Wchar (T (Ptr2));
  235.             Ptr2 := Ptr2 + 1;
  236.          end loop;
  237.  
  238.          Write_Eol;
  239.  
  240.          Write_Str ("     ");
  241.          Col := 0;
  242.  
  243.          while Ptr1 < P loop
  244.             if T (Ptr1) = HT then
  245.                Wchar (HT);
  246.             else
  247.                Wchar (' ');
  248.             end if;
  249.  
  250.             Ptr1 := Ptr1 + 1;
  251.          end loop;
  252.  
  253.          Wchar ('|');
  254.          Write_Eol;
  255.  
  256.          Exit_Program (E_Fatal);
  257.       end Fatal_Error;
  258.  
  259.       ----------
  260.       -- Getc --
  261.       ----------
  262.  
  263.       function Getc return Character is
  264.       begin
  265.          if P = T'Last then
  266.             return EOF;
  267.          else
  268.             P := P + 1;
  269.             return T (P - 1);
  270.          end if;
  271.       end Getc;
  272.  
  273.       --------------
  274.       -- Get_Name --
  275.       --------------
  276.  
  277.       function Get_Name return Name_Id is
  278.       begin
  279.          Name_Len := 0;
  280.          Skip_Space;
  281.  
  282.          if At_Eol then
  283.             Fatal_Error;
  284.          end if;
  285.  
  286.          loop
  287.             Name_Len := Name_Len + 1;
  288.             Name_Buffer (Name_Len) := Getc;
  289.             exit when At_End_Of_Field;
  290.          end loop;
  291.  
  292.          return Name_Find;
  293.       end Get_Name;
  294.  
  295.       -------------
  296.       -- Get_Nat --
  297.       -------------
  298.  
  299.       function Get_Nat return Nat is
  300.          V : Nat;
  301.  
  302.       begin
  303.          V := 0;
  304.  
  305.          loop
  306.             V := V * 10 + (Character'Pos (Getc) - Character'Pos ('0'));
  307.             exit when At_End_Of_Field;
  308.          end loop;
  309.  
  310.          return V;
  311.       end Get_Nat;
  312.  
  313.       ---------------
  314.       -- Get_Stamp --
  315.       ---------------
  316.  
  317.       function Get_Stamp return Time_Stamp_Type is
  318.          T : Time_Stamp_Type;
  319.  
  320.       begin
  321.          Skip_Space;
  322.  
  323.          if At_Eol then
  324.             Fatal_Error;
  325.          end if;
  326.  
  327.          for J in T'Range loop
  328.             T (J) := Getc;
  329.          end loop;
  330.  
  331.          return T;
  332.       end Get_Stamp;
  333.  
  334.       --------------
  335.       -- Skip_Eol --
  336.       --------------
  337.  
  338.       procedure Skip_Eol is
  339.       begin
  340.          Skip_Space;
  341.          if not At_Eol then Fatal_Error; end if;
  342.  
  343.          --  Loop to skip past blank lines (first time through skips this EOL)
  344.  
  345.          while T (P) < ' ' and then T (P) /= EOF loop
  346.             if T (P) = LF then
  347.                Line := Line + 1;
  348.             end if;
  349.  
  350.             P := P + 1;
  351.          end loop;
  352.       end Skip_Eol;
  353.  
  354.       ----------------
  355.       -- Skip_Space --
  356.       ----------------
  357.  
  358.       procedure Skip_Space is
  359.       begin
  360.          while T (P) = ' ' or else T (P) = HT loop
  361.             P := P + 1;
  362.          end loop;
  363.       end Skip_Space;
  364.  
  365.    --------------------------------------
  366.    -- Start of processing for Scan_ALI --
  367.    --------------------------------------
  368.  
  369.    begin
  370.       ALIs.Increment_Last;
  371.       Id := ALIs.Last;
  372.       Set_Name_Table_Info (F, Int (Id));
  373.  
  374.       ALIs.Table (Id).Afile := F;
  375.       ALIs.Table (Id).Ofile_Full_Name := Full_Object_File_Name;
  376.       ALIs.Table (Id).First_Unit := No_Unit_Id;
  377.  
  378.       --  Acquire library version
  379.  
  380.       Checkc ('V');
  381.       Checkc (' ');
  382.       Checkc ('"');
  383.  
  384.       for J in ALIs.Table (Id).Ver'Range loop
  385.          ALIs.Table (Id).Ver (J) := Getc;
  386.       end loop;
  387.  
  388.       Checkc ('"');
  389.       Skip_Eol;
  390.  
  391.       --  Acquire standard version
  392.  
  393.       Checkc ('S');
  394.       Checkc (' ');
  395.       Checkc ('"');
  396.  
  397.       for J in ALIs.Table (Id).Std'Range loop
  398.          ALIs.Table (Id).Std (J) := Getc;
  399.       end loop;
  400.  
  401.       Checkc ('"');
  402.       Skip_Eol;
  403.  
  404.       --  Acquire main program line if present
  405.  
  406.       C := Getc;
  407.  
  408.       if C = 'M' then
  409.          Checkc (' ');
  410.  
  411.          C := Getc;
  412.  
  413.          if C = 'F' then
  414.             ALIs.Table (Id).Main_Program := Func;
  415.          elsif C = 'P' then
  416.             ALIs.Table (Id).Main_Program := Proc;
  417.          else
  418.             P := P - 1;
  419.             Fatal_Error;
  420.          end if;
  421.  
  422.          Skip_Space;
  423.  
  424.          if not At_Eol then
  425.             ALIs.Table (Id).Main_Priority := Get_Nat;
  426.          else
  427.             ALIs.Table (Id).Main_Priority := No_Main_Priority;
  428.          end if;
  429.  
  430.          Skip_Eol;
  431.          C := Getc;
  432.  
  433.       else
  434.          ALIs.Table (Id).Main_Program  := None;
  435.          ALIs.Table (Id).Main_Priority := No_Main_Priority;
  436.       end if;
  437.  
  438.       --  Skip argument lines
  439.  
  440.       Arg_Loop : while C = 'A' loop
  441.          while not At_Eol loop
  442.             C := Getc;
  443.          end loop;
  444.  
  445.          Skip_Eol;
  446.          C := Getc;
  447.       end loop Arg_Loop;
  448.  
  449.       --  Loop to acquire unit entries
  450.  
  451.       Unit_Loop : while C = 'U' loop
  452.          Checkc (' ');
  453.          Unit.Increment_Last;
  454.  
  455.          if ALIs.Table (Id).First_Unit = No_Unit_Id then
  456.             ALIs.Table (Id).First_Unit := Unit.Last;
  457.          end if;
  458.  
  459.          Unit.Table (Unit.Last).Uname          := Get_Name;
  460.          Unit.Table (Unit.Last).Predefined     := Is_Predefined_Unit;
  461.          Unit.Table (Unit.Last).My_ALI         := Id;
  462.          Unit.Table (Unit.Last).Sfile          := Get_Name;
  463.          Unit.Table (Unit.Last).Pure           := False;
  464.          Unit.Table (Unit.Last).Preelab        := False;
  465.          Unit.Table (Unit.Last).No_Elab        := False;
  466.          Unit.Table (Unit.Last).Shared_Passive := False;
  467.          Unit.Table (Unit.Last).RCI            := False;
  468.          Unit.Table (Unit.Last).Remote_Types   := False;
  469.          Unit.Table (Unit.Last).Elaborate_Body := False;
  470.          Unit.Table (Unit.Last).Version        := "00000000";
  471.          Unit.Table (Unit.Last).First_With     := Withs.Last + 1;
  472.  
  473.          Set_Name_Table_Info (Unit.Table (Unit.Last).Uname, Int (Unit.Last));
  474.  
  475.          --  Scan out possible version and other parameters
  476.  
  477.          loop
  478.             Skip_Space;
  479.             exit when At_Eol;
  480.             C := Getc;
  481.  
  482.             --  Version field
  483.  
  484.             if C in '0' .. '9' or else C in 'a' .. 'f' then
  485.                Unit.Table (Unit.Last).Version (1) := C;
  486.  
  487.                for J in 2 .. 8 loop
  488.                   C := Getc;
  489.                   Unit.Table (Unit.Last).Version (J) := C;
  490.                end loop;
  491.  
  492.             --  EB parameter (elaborate body)
  493.  
  494.             elsif C = 'E' then
  495.                Checkc ('B');
  496.                Check_At_End_Of_Field;
  497.                Unit.Table (Unit.Last).Elaborate_Body := True;
  498.  
  499.             --  NE parameter (no elaboration)
  500.  
  501.             elsif C = 'N' then
  502.                Checkc ('E');
  503.                Check_At_End_Of_Field;
  504.                Unit.Table (Unit.Last).No_Elab := True;
  505.  
  506.             --  PR/PU/PK parameters
  507.  
  508.             elsif C = 'P' then
  509.                C := Getc;
  510.  
  511.                --  PR parameter (preelaborate) (also allow PRE for back
  512.                --  compatibility with versions 2.03 and earlier)
  513.  
  514.                if C = 'R' then
  515.                   if not At_End_Of_Field then
  516.                      Checkc ('E');
  517.                      Check_At_End_Of_Field;
  518.                   end if;
  519.  
  520.                   Unit.Table (Unit.Last).Preelab := True;
  521.  
  522.                --  PU parameter (pure)
  523.  
  524.                elsif C = 'U' then
  525.                   Check_At_End_Of_Field;
  526.                   Unit.Table (Unit.Last).Pure := True;
  527.  
  528.                --  PK indicates unit is package
  529.  
  530.                elsif C = 'K' then
  531.                   Check_At_End_Of_Field;
  532.  
  533.                else
  534.                   Fatal_Error;
  535.                end if;
  536.  
  537.             --  RC/RT parameters
  538.  
  539.             elsif C = 'R' then
  540.                C := Getc;
  541.  
  542.                --  RC parameter (remote call interface)
  543.  
  544.                if C = 'C' then
  545.                   Check_At_End_Of_Field;
  546.                   Unit.Table (Unit.Last).RCI := True;
  547.  
  548.                --  RT parameter (remote types)
  549.  
  550.                elsif C = 'T' then
  551.                   Check_At_End_Of_Field;
  552.                   Unit.Table (Unit.Last).Remote_Types := True;
  553.  
  554.                else
  555.                   Fatal_Error;
  556.                end if;
  557.  
  558.             elsif C = 'S' then
  559.                C := Getc;
  560.  
  561.                --  SP parameter (shared passive)
  562.  
  563.                if C = 'P' then
  564.                   Check_At_End_Of_Field;
  565.                   Unit.Table (Unit.Last).Shared_Passive := True;
  566.  
  567.                --  SU parameter indicates unit is subprogram
  568.  
  569.                elsif C = 'U' then
  570.                   Check_At_End_Of_Field;
  571.  
  572.                else
  573.                   Fatal_Error;
  574.                end if;
  575.  
  576.             else
  577.                Fatal_Error;
  578.             end if;
  579.          end loop;
  580.  
  581.          Skip_Eol;
  582.  
  583.          --  Scan out With lines for this unit
  584.  
  585.          C := Getc;
  586.  
  587.          With_Loop : while C = 'W' loop
  588.             Checkc (' ');
  589.             Withs.Increment_Last;
  590.             Withs.Table (Withs.Last).Uname         := Get_Name;
  591.             Withs.Table (Withs.Last).Elaborate     := False;
  592.             Withs.Table (Withs.Last).Elaborate_All := False;
  593.  
  594.             --  Generic case
  595.  
  596.             if At_Eol then
  597.                Withs.Table (Withs.Last).Sfile := No_File;
  598.                Withs.Table (Withs.Last).Afile := No_File;
  599.  
  600.             --  Normal case
  601.  
  602.             else
  603.                Withs.Table (Withs.Last).Sfile := Get_Name;
  604.                Withs.Table (Withs.Last).Afile := Get_Name;
  605.  
  606.                --  Scan out possible E and EA parameters
  607.  
  608.                while not At_Eol loop
  609.                   Skip_Space;
  610.  
  611.                   if Getc = 'E' then
  612.                      if At_End_Of_Field then
  613.                         Withs.Table (Withs.Last).Elaborate := True;
  614.                      else
  615.                         Checkc ('A');
  616.                         Check_At_End_Of_Field;
  617.                         Withs.Table (Withs.Last).Elaborate_All := True;
  618.                      end if;
  619.                   end if;
  620.                end loop;
  621.             end if;
  622.  
  623.             Skip_Eol;
  624.             C := Getc;
  625.  
  626.          end loop With_Loop;
  627.  
  628.          Unit.Table (Unit.Last).Last_With  := Withs.Last;
  629.  
  630.       end loop Unit_Loop;
  631.  
  632.       --  End loop through units for one ALI file
  633.  
  634.       ALIs.Table (Id).Last_Unit := Unit.Last;
  635.       ALIs.Table (Id).Sfile := Unit.Table (ALIs.Table (Id).First_Unit).Sfile;
  636.  
  637.       --  Set types of the units (there can be at most 2 of them)
  638.  
  639.       if ALIs.Table (Id).First_Unit /= ALIs.Table (Id).Last_Unit then
  640.          Unit.Table (ALIs.Table (Id).First_Unit).Utype := Is_Body;
  641.          Unit.Table (ALIs.Table (Id).Last_Unit).Utype  := Is_Spec;
  642.  
  643.       else
  644.          --  Deal with body only and spec only cases, note that the reason we
  645.          --  do our own checking of the name (rather than using Is_Body_Name)
  646.          --  is that Uname drags in far too much compiler junk!
  647.  
  648.          Get_Name_String (Unit.Table (Unit.Last).Uname);
  649.  
  650.          if Name_Buffer (Name_Len) = 'b' then
  651.             Unit.Table (Unit.Last).Utype := Is_Body_Only;
  652.          else
  653.             Unit.Table (Unit.Last).Utype := Is_Spec_Only;
  654.          end if;
  655.       end if;
  656.  
  657.       --  If there are linker options lines present, scan them
  658.  
  659.       while C = 'L' loop
  660.          Checkc (' ');
  661.          Checkc ('"');
  662.  
  663.          declare
  664.             Lbuf : String (1 .. 200);
  665.             Llen : Natural := 0;
  666.             Lptr : Natural;
  667.             HC   : Natural;
  668.             Dup  : Boolean;
  669.             Tptr : Natural;
  670.  
  671.          begin
  672.             loop
  673.                C := Getc;
  674.  
  675.                if C < ' ' then
  676.                   Fatal_Error;
  677.                end if;
  678.  
  679.                exit when C = '"';
  680.                Llen := Llen + 1;
  681.                Lbuf (Llen) := C;
  682.             end loop;
  683.  
  684.             Llen := Llen + 1;
  685.             Lbuf (Llen) := Ascii.NUL;
  686.  
  687.             Skip_Eol;
  688.             C := Getc;
  689.  
  690.             --  Now see if we already have this string stored
  691.  
  692.             Dup := False;
  693.             Lptr := 0;
  694.             Tptr := 1;
  695.  
  696.             while Tptr <= Linker_Options.Last loop
  697.                Lptr := Lptr + 1;
  698.  
  699.                if Linker_Options.Table (Tptr) = Lbuf (Lptr) then
  700.                   if Lptr = Llen then
  701.                      Dup := True;
  702.                      exit;
  703.                   end if;
  704.  
  705.                elsif Linker_Options.Table (Tptr) = Ascii.Nul then
  706.                   Lptr := 0;
  707.  
  708.                else
  709.                   loop
  710.                      Tptr := Tptr + 1;
  711.                      exit when Linker_Options.Table (Tptr) = Ascii.NUL;
  712.                   end loop;
  713.  
  714.                   Lptr := 0;
  715.                end if;
  716.  
  717.                Tptr := Tptr + 1;
  718.             end loop;
  719.  
  720.             --  If not a duplicate, add new string to table
  721.  
  722.             if not Dup then
  723.                for J in 1 .. Llen loop
  724.                   Linker_Options.Increment_Last;
  725.                   Linker_Options.Table (Linker_Options.Last) := Lbuf (J);
  726.                end loop;
  727.             end if;
  728.          end;
  729.       end loop;
  730.  
  731.       --  Scan out source dependency lines for this ALI file
  732.  
  733.       ALIs.Table (Id).First_Sdep := Sdep.Last + 1;
  734.  
  735.       while C = 'D' loop
  736.          Checkc (' ');
  737.          Sdep.Increment_Last;
  738.          Sdep.Table (Sdep.Last).Sfile := Get_Name;
  739.          Sdep.Table (Sdep.Last).Stamp := Get_Stamp;
  740.  
  741.          --  Skip comments after stamp
  742.  
  743.          while not At_Eol loop
  744.             P := P + 1;
  745.          end loop;
  746.  
  747.          Skip_Eol;
  748.          C := Getc;
  749.       end loop;
  750.  
  751.       ALIs.Table (Id).Last_Sdep := Sdep.Last;
  752.  
  753.       if C /= EOF then
  754.          Fatal_Error;
  755.       end if;
  756.  
  757.       return Id;
  758.    end Scan_ALI;
  759.  
  760.    ----------------------
  761.    -- Set_Source_Table --
  762.    ----------------------
  763.  
  764.    procedure Set_Source_Table (A : ALI_Id) is
  765.       F : File_Name_Type;
  766.       S : Source_Id;
  767.       Stamp : Time_Stamp_Type;
  768.  
  769.    begin
  770.       Sdep_Loop : for D in
  771.         ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep
  772.       loop
  773.          F := Sdep.Table (D).Sfile;
  774.  
  775.          --  If this is the first time we are seeing this source file,
  776.          --  then make a new entry in the source table.
  777.  
  778.          if Get_Name_Table_Info (F) = 0 then
  779.             Source.Increment_Last;
  780.             S := Source.Last;
  781.             Set_Name_Table_Info (F, Int (S));
  782.             Source.Table (S).Sfile := F;
  783.  
  784.             --  In check source files mode, try to get stamp from file
  785.  
  786.             if Check_Source_Files then
  787.                Stamp := Source_File_Stamp (F);
  788.  
  789.                --  If we got the stamp, then set the stamp in the source
  790.                --  table entry and mark it as set from the source so that
  791.                --  it does not get subsequently changed.
  792.  
  793.                if Stamp (Stamp'First) /= ' ' then
  794.                   Source.Table (S).Stamp := Stamp;
  795.                   Source.Table (S).Source_Found := True;
  796.  
  797.                --  If we could not find the file, then the stamp is set
  798.                --  from the dependency table entry (to be possibly reset
  799.                --  if we find a later stamp in subsequent processing)
  800.  
  801.                else
  802.                   Source.Table (S).Stamp := Sdep.Table (D).Stamp;
  803.                   Source.Table (S).Source_Found := False;
  804.  
  805.                   --  In All_Sources mode, flag error of file not found
  806.  
  807.                   if All_Sources then
  808.                      Error_Msg_Name_1 := F;
  809.                      Error_Msg ("cannot locate %");
  810.                   end if;
  811.                end if;
  812.  
  813.             --  First time for this source file, but Check_Source_Files
  814.             --  is off, so simply initialize the stamp from the Sdep entry
  815.  
  816.             else
  817.                Source.Table (S).Source_Found := False;
  818.                Source.Table (S).Stamp := Sdep.Table (D).Stamp;
  819.             end if;
  820.  
  821.          --  Here if this is not the first time for this source file,
  822.          --  so that the source table entry is already constructed.
  823.  
  824.          else
  825.             S := Source_Id (Get_Name_Table_Info (F));
  826.  
  827.             --  If stamp was set from source file don't touch it. Otherwise
  828.             --  update the stamp if the current reference in the Sdep entry
  829.             --  is later than the current entry in the source table unless
  830.             --  we find the corresponding source file and its time stamp
  831.             --  matches the earlier one.
  832.  
  833.             if not Source.Table (S).Source_Found
  834.               and then Sdep.Table (D).Stamp /= Source.Table (S).Stamp
  835.             then
  836.                Stamp := Source_File_Stamp (F);
  837.  
  838.                if Stamp = Source.Table (S).Stamp then
  839.                   null;
  840.                elsif Stamp = Sdep.Table (D).Stamp
  841.                  or else Later (Sdep.Table (D).Stamp, Source.Table (S).Stamp)
  842.                then
  843.                   Source.Table (S).Stamp := Sdep.Table (D).Stamp;
  844.                end if;
  845.  
  846.                if Stamp = Source.Table (S).Stamp then
  847.                   Source.Table (S).Source_Found := True;
  848.                end if;
  849.             end if;
  850.          end if;
  851.  
  852.       end loop Sdep_Loop;
  853.  
  854.    end Set_Source_Table;
  855.  
  856.    ----------------------
  857.    -- Set_Source_Table --
  858.    ----------------------
  859.  
  860.    procedure Set_Source_Table is
  861.    begin
  862.       for A in ALIs.First .. ALIs.Last loop
  863.          Set_Source_Table (A);
  864.       end loop;
  865.  
  866.    end Set_Source_Table;
  867.  
  868.    -------------------------
  869.    -- Time_Stamp_Mismatch --
  870.    -------------------------
  871.  
  872.    function Time_Stamp_Mismatch (A : ALI_Id) return File_Name_Type is
  873.       Src : Source_Id;
  874.       --  Source file Id for the current Sdep entry
  875.  
  876.    begin
  877.       for D in ALIs.Table (A).First_Sdep .. ALIs.Table (A).Last_Sdep loop
  878.          Src := Source_Id (Get_Name_Table_Info (Sdep.Table (D).Sfile));
  879.  
  880.          if not Source.Table (Src).Source_Found
  881.            or else Sdep.Table (D).Stamp /= Source.Table (Src).Stamp
  882.          then
  883.             return Source.Table (Src).Sfile;
  884.          end if;
  885.       end loop;
  886.  
  887.       return No_File;
  888.  
  889.    end Time_Stamp_Mismatch;
  890.  
  891. end ALI;
  892.