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 / sinput.adb < prev    next >
Text File  |  1996-09-28  |  20KB  |  646 lines

  1. ------------------------------------------------------------------------------
  2. --                                                                          --
  3. --                         GNAT COMPILER COMPONENTS                         --
  4. --                                                                          --
  5. --                               S I N P U T                                --
  6. --                                                                          --
  7. --                                 B o d y                                  --
  8. --                                                                          --
  9. --                            $Revision: 1.52 $                             --
  10. --                                                                          --
  11. --        Copyright (c) 1992,1993,1994,1995 NYU, All Rights Reserved        --
  12. --                                                                          --
  13. -- The GNAT library is free software; you can redistribute it and/or modify --
  14. -- it under terms of the GNU Library General Public License as published by --
  15. -- the Free Software  Foundation; either version 2, or (at your option) any --
  16. -- later version.  The GNAT library is distributed in the hope that it will --
  17. -- be useful, but WITHOUT ANY WARRANTY;  without even  the implied warranty --
  18. -- of MERCHANTABILITY  or  FITNESS FOR  A PARTICULAR PURPOSE.  See the  GNU --
  19. -- Library  General  Public  License for  more  details.  You  should  have --
  20. -- received  a copy of the GNU  Library  General Public License  along with --
  21. -- the GNAT library;  see the file  COPYING.LIB.  If not, write to the Free --
  22. -- Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.        --
  23. --                                                                          --
  24. ------------------------------------------------------------------------------
  25.  
  26. with Alloc;   use Alloc;
  27. with Debug;   use Debug;
  28. with Namet;   use Namet;
  29. with Output;  use Output;
  30. with Tree_IO; use Tree_IO;
  31.  
  32. package body Sinput is
  33.  
  34.    use Ascii;
  35.    --  Make control characters visible
  36.  
  37.    -----------------------
  38.    -- Local Subprograms --
  39.    -----------------------
  40.  
  41.    function Line_Offset (S : Source_File_Index) return Int;
  42.    pragma Inline (Line_Offset);
  43.    --  This value is never referenced directly by clients (who should use
  44.    --  the Logical_To_Physical or Physical_To_Logical functions instead).
  45.  
  46.    -----------------
  47.    -- Backup_Line --
  48.    -----------------
  49.  
  50.    procedure Backup_Line (P : in out Source_Ptr) is
  51.       Sindex : constant Source_File_Index := Get_Source_File_Index (P);
  52.       Src    : constant Source_Buffer_Ptr :=
  53.                  Source_File.Table (Sindex).Source_Text;
  54.       Sfirst : constant Source_Ptr :=
  55.                  Source_File.Table (Sindex).Source_First;
  56.  
  57.    begin
  58.       P := P - 1;
  59.  
  60.       if P = Sfirst then
  61.          return;
  62.       end if;
  63.  
  64.       if Src (P) = CR then
  65.          if Src (P - 1) = LF then
  66.             P := P - 1;
  67.          end if;
  68.  
  69.       else -- Src (P) = LF
  70.          if Src (P - 1) = CR then
  71.             P := P - 1;
  72.          end if;
  73.       end if;
  74.  
  75.       --  Now find first character of the previous line
  76.  
  77.       while P > Sfirst
  78.         and then Src (P - 1) /= LF
  79.         and then Src (P - 1) /= CR
  80.       loop
  81.          P := P - 1;
  82.       end loop;
  83.    end Backup_Line;
  84.  
  85.    -----------------------
  86.    -- Get_Column_Number --
  87.    -----------------------
  88.  
  89.    function Get_Column_Number (P : Source_Ptr) return Column_Number is
  90.       S      : Source_Ptr;
  91.       C      : Column_Number;
  92.       Sindex : Source_File_Index;
  93.       Src    : Source_Buffer_Ptr;
  94.  
  95.    begin
  96.       --  If the input source pointer is not a meaningful value then return
  97.       --  at once with column number 1. This can happen for a file not found
  98.       --  condition for a file loaded indirectly by RTE, and also perhaps on
  99.       --  some unknown internal error conditions. In either case we certainly
  100.       --  don't want to blow up. It can also happen in gnatf when trying
  101.       --  to find the full view of an incomplete type whose completion is
  102.       --  is in the body.
  103.  
  104.       if P < 1 then
  105.          return 1;
  106.  
  107.       else
  108.          Sindex := Get_Source_File_Index (P);
  109.          Src := Source_File.Table (Sindex).Source_Text;
  110.          S := Line_Start (P);
  111.          C := 1;
  112.  
  113.          while S < P loop
  114.             if Src (S) = HT then
  115.                C := (C - 1) / 8 * 8 + (8 + 1);
  116.             else
  117.                C := C + 1;
  118.             end if;
  119.  
  120.             S := S + 1;
  121.          end loop;
  122.  
  123.          return C;
  124.       end if;
  125.    end Get_Column_Number;
  126.  
  127.    ---------------------
  128.    -- Get_Line_Number --
  129.    ---------------------
  130.  
  131.    function Get_Line_Number (P : Source_Ptr) return Logical_Line_Number is
  132.       Sfile : Source_File_Index;
  133.       Table : Lines_Table_Ptr;
  134.       Lo    : Nat;
  135.       Hi    : Nat;
  136.       Mid   : Nat;
  137.       Loc   : Source_Ptr;
  138.  
  139.    begin
  140.       --  If the input source pointer is not a meaningful value then return
  141.       --  at once with line number 1. This can happen for a file not found
  142.       --  condition for a file loaded indirectly by RTE, and also perhaps on
  143.       --  some unknown internal error conditions. In either case we certainly
  144.       --  don't want to blow up.
  145.  
  146.       if P < 1 then
  147.          return 1;
  148.  
  149.       --  Otherwise we can do the binary search
  150.  
  151.       else
  152.          Sfile := Get_Source_File_Index (P);
  153.          Loc   := P + Source_File.Table (Sfile).Sloc_Adjust;
  154.          Table := Source_File.Table (Sfile).Lines_Table;
  155.          Lo    := 1;
  156.          Hi    := Source_File.Table (Sfile).Num_Source_Lines;
  157.  
  158.          loop
  159.             Mid := (Lo + Hi) / 2;
  160.  
  161.             if Loc < Table (Mid) then
  162.                Hi := Mid - 1;
  163.  
  164.             else -- Loc >= Table (Mid)
  165.  
  166.                if Mid = Hi or else
  167.                   Loc < Table (Mid + 1)
  168.                then
  169.                   return Logical_Line_Number (Mid + Line_Offset (Sfile));
  170.                else
  171.                   Lo := Mid + 1;
  172.                end if;
  173.  
  174.             end if;
  175.  
  176.          end loop;
  177.       end if;
  178.    end Get_Line_Number;
  179.  
  180.    ---------------------------
  181.    -- Get_Source_File_Index --
  182.    ---------------------------
  183.  
  184.    Source_Cache_First : Source_Ptr := 1;
  185.    Source_Cache_Last  : Source_Ptr := 0;
  186.    --  Records the First and Last subscript values for the most recently
  187.    --  referenced entry in the source table, to optimize the common case
  188.    --  of repeated references to the same entry. The initial values force
  189.    --  an initial search to set the cache value.
  190.  
  191.    Source_Cache_Index : Source_File_Index := No_Source_File;
  192.    --  Contains the index of the entry corresponding to Source_Cache
  193.  
  194.    function Get_Source_File_Index
  195.      (S    : Source_Ptr)
  196.       return Source_File_Index
  197.    is
  198.    begin
  199.       if S in Source_Cache_First .. Source_Cache_Last then
  200.          return Source_Cache_Index;
  201.  
  202.       else
  203.          for J in 1 .. Source_File.Last loop
  204.             if S in Source_File.Table (J).Source_First ..
  205.                     Source_File.Table (J).Source_Last
  206.             then
  207.                Source_Cache_Index := J;
  208.                Source_Cache_First :=
  209.                  Source_File.Table (Source_Cache_Index).Source_First;
  210.                Source_Cache_Last :=
  211.                  Source_File.Table (Source_Cache_Index).Source_Last;
  212.                return Source_Cache_Index;
  213.             end if;
  214.          end loop;
  215.       end if;
  216.  
  217.       pragma Assert (False);
  218.    end Get_Source_File_Index;
  219.  
  220.    ----------------------
  221.    -- Last_Source_File --
  222.    ----------------------
  223.  
  224.    function Last_Source_File return Source_File_Index is
  225.    begin
  226.       return Source_File.Last;
  227.    end Last_Source_File;
  228.  
  229.    ----------------
  230.    -- Line_Start --
  231.    ----------------
  232.  
  233.    function Line_Start (P : Source_Ptr) return Source_Ptr is
  234.       Sindex : constant Source_File_Index := Get_Source_File_Index (P);
  235.       Src    : constant Source_Buffer_Ptr :=
  236.                  Source_File.Table (Sindex).Source_Text;
  237.       Sfirst : constant Source_Ptr :=
  238.                  Source_File.Table (Sindex).Source_First;
  239.       S      : Source_Ptr;
  240.  
  241.    begin
  242.       S := P;
  243.  
  244.       while S > Sfirst
  245.         and then Src (S - 1) /= CR
  246.         and then Src (S - 1) /= LF
  247.       loop
  248.          S := S - 1;
  249.       end loop;
  250.  
  251.       return S;
  252.    end Line_Start;
  253.  
  254.    ----------------
  255.    -- Line_Start --
  256.    ----------------
  257.  
  258.    function Line_Start
  259.      (L    : Logical_Line_Number;
  260.       S    : Source_File_Index)
  261.       return Source_Ptr
  262.    is
  263.    begin
  264.       return Source_File.Table (S).Lines_Table (Logical_To_Physical (L, S));
  265.    end Line_Start;
  266.  
  267.    -------------------------
  268.    -- Logical_To_Physical --
  269.    -------------------------
  270.  
  271.    function Logical_To_Physical
  272.      (Line : Logical_Line_Number;
  273.       S    : Source_File_Index)
  274.       return Nat
  275.    is
  276.    begin
  277.       if Line = 1 then
  278.          return 1;
  279.       else
  280.          return Nat (Line) - Line_Offset (S);
  281.       end if;
  282.    end Logical_To_Physical;
  283.  
  284.    -------------------------
  285.    -- Physical_To_Logical --
  286.    -------------------------
  287.  
  288.    function Physical_To_Logical
  289.      (Line : Nat;
  290.       S    : Source_File_Index)
  291.       return Logical_Line_Number
  292.    is
  293.    begin
  294.       if Line = 1 then
  295.          return 1;
  296.       else
  297.          return Logical_Line_Number (Line + Line_Offset (S));
  298.       end if;
  299.    end Physical_To_Logical;
  300.  
  301.    ----------------------
  302.    -- Num_Source_Files --
  303.    ----------------------
  304.  
  305.    function Num_Source_Files return Nat is
  306.    begin
  307.       return Int (Source_File.Last) - Int (Source_File.First) + 1;
  308.    end Num_Source_Files;
  309.  
  310.    ---------------------------
  311.    -- Skip_Line_Terminators --
  312.    ---------------------------
  313.  
  314.    --  There are two distinct concepts of line terminator in GNAT
  315.  
  316.    --    A logical line terminator is what corresponds to the "end of a line"
  317.    --    as described in RM 2.2 (13). Any of the characters FF, LF, CR or VT
  318.    --    acts as an end of logical line in this sense, and it is essentially
  319.    --    irrelevant whether one or more appears in sequence (since if a
  320.    --    sequence of such characters is regarded as separate ends of line,
  321.    --    then the intervening logical lines are null in any case).
  322.  
  323.    --    A physical line terminator is a sequence of format effectors that
  324.    --    is treated as ending a physical line. Physical lines have no Ada
  325.    --    semantic significance, but they are significant for error reporting
  326.    --    purposes, since errors are identified by line and column location.
  327.  
  328.    --  In GNAT, a physical line is ended by any of the sequences LF, CR/LF,
  329.    --  CR or LF/CR. LF is used in typical Unix systems, CR/LF in DOS systems,
  330.    --  and CR alone in System 7. We don't know of any system using LF/CR, but
  331.    --  it seems reasonable to include this case for consistency. In addition,
  332.    --  we recognize any of these sequences in any of the operating systems,
  333.    --  for better behavior in treating foreign files (e.g. a Unix file with
  334.    --  LF terminators transferred to a DOS system).
  335.  
  336.    procedure Skip_Line_Terminators
  337.      (P        : in out Source_Ptr;
  338.       Physical : out Boolean)
  339.    is
  340.    begin
  341.       pragma Assert (Source (P) in Line_Terminator);
  342.  
  343.       if Source (P) = CR then
  344.          if Source (P + 1) = LF then
  345.             P := P + 2;
  346.          else
  347.             P := P + 1;
  348.          end if;
  349.  
  350.       elsif Source (P) = LF then
  351.          if Source (P + 1) = CR then
  352.             P := P + 2;
  353.          else
  354.             P := P + 1;
  355.          end if;
  356.  
  357.       else -- Source (P) = FF or else Source (P) = VT
  358.          P := P + 1;
  359.          Physical := False;
  360.          return;
  361.       end if;
  362.  
  363.       --  Fall through in the physical line terminator case. First deal with
  364.       --  making a possible entry into the lines table if one is needed.
  365.  
  366.       --  Note: we are dealing with a real source file here, this cannot be
  367.       --  the instantiation case, so we need not worry about Sloc adjustment.
  368.  
  369.       declare
  370.          Lines_Table : Lines_Table_Ptr :=
  371.            Source_File.Table (Current_Source_File).Lines_Table;
  372.  
  373.          Num_Source_Lines : Nat :=
  374.            Source_File.Table (Current_Source_File).Num_Source_Lines;
  375.  
  376.       begin
  377.          Physical := True;
  378.  
  379.          --  Make entry in lines table if not already made (in some scan backup
  380.          --  cases, we will be rescanning previously scanned source, so the
  381.          --  entry may have already been made on the previous forward scan).
  382.  
  383.          if Source (P) /= EOF
  384.            and then P > Lines_Table (Num_Source_Lines)
  385.          then
  386.  
  387.             --  Reallocate the lines table if it has got too large. Note that
  388.             --  we don't use the normal Table package mechanism because we
  389.             --  have several of these tables, one for each source file.
  390.  
  391.             if Num_Source_Lines = Lines_Table'Last then
  392.  
  393.                declare
  394.                   New_Lines_Table : Lines_Table_Ptr :=
  395.                      new Lines_Table_Type
  396.                        (1 .. Num_Source_Lines *
  397.                                (100 + Alloc_Lines_Increment) / 100);
  398.                begin
  399.                   if Debug_Flag_D then
  400.                      Write_Str ("--> Allocating new lines table, size = ");
  401.                      Write_Int (Int (New_Lines_Table'Last));
  402.                      Write_Eol;
  403.                   end if;
  404.  
  405.                   New_Lines_Table (1 .. Lines_Table'Last) :=
  406.                     Lines_Table (1 .. Lines_Table'Last);
  407.                   Free_Lines (Lines_Table);
  408.                   Lines_Table := New_Lines_Table;
  409.                   Source_File.Table (Current_Source_File).Lines_Table :=
  410.                     Lines_Table;
  411.                end;
  412.             end if;
  413.  
  414.             Num_Source_Lines := Num_Source_Lines + 1;
  415.             Lines_Table (Num_Source_Lines) := P;
  416.             Source_File.Table (Current_Source_File).Num_Source_Lines :=
  417.               Num_Source_Lines;
  418.          end if;
  419.       end;
  420.    end Skip_Line_Terminators;
  421.  
  422.    ---------------
  423.    -- Tree_Read --
  424.    ---------------
  425.  
  426.    procedure Tree_Read is
  427.    begin
  428.       Source_File.Tree_Read;
  429.  
  430.       --  The pointers we read in there for the source buffer and lines
  431.       --  table pointers are junk. We now read in the actual data that
  432.       --  is referenced by these two fields.
  433.  
  434.       for J in Source_File.First .. Source_File.Last loop
  435.          declare
  436.             Buf  : Source_Buffer_Ptr;
  437.             Fbuf : Text_Ptr;
  438.             Lbuf : Text_Ptr;
  439.  
  440.             Lins : Lines_Table_Ptr;
  441.             Flin : Nat;
  442.             Llin : Nat;
  443.  
  444.          begin
  445.             Tree_Read_Int (Int (Fbuf));
  446.             Tree_Read_Int (Int (Lbuf));
  447.             Buf := new Text_Buffer (Fbuf .. Lbuf);
  448.             Tree_Read_Data (Buf (Fbuf)'Address, Int (Lbuf - Fbuf + 1));
  449.             Source_File.Table (J).Source_Text := Buf;
  450.  
  451.             Tree_Read_Int (Flin);
  452.             Tree_Read_Int (Llin);
  453.             Lins := new Lines_Table_Type (Flin .. Llin);
  454.             Tree_Read_Data (Lins (Flin)'Address, Int (Llin - Flin + 1));
  455.             Source_File.Table (J).Lines_Table := Lins;
  456.          end;
  457.       end loop;
  458.    end Tree_Read;
  459.  
  460.    ----------------
  461.    -- Tree_Write --
  462.    ----------------
  463.  
  464.    procedure Tree_Write is
  465.    begin
  466.       Source_File.Tree_Write;
  467.  
  468.       --  The pointers we wrote out there for the source buffer and lines
  469.       --  table pointers are junk, we now write out the actual data that
  470.       --  is referenced by these two fields.
  471.  
  472.       for J in Source_File.First .. Source_File.Last loop
  473.          declare
  474.             Buf  : Source_Buffer_Ptr :=
  475.                      Source_File.Table (J).Source_Text;
  476.  
  477.             Fbuf : constant Text_Ptr := Buf.all'First;
  478.             Lbuf : constant Text_Ptr := Buf.all'Last;
  479.  
  480.             Lins : constant Lines_Table_Ptr :=
  481.                      Source_File.Table (J).Lines_Table;
  482.  
  483.             Flin : constant Nat := Lins.all'First;
  484.             Llin : constant Nat := Lins.all'Last;
  485.  
  486.          begin
  487.             Tree_Write_Int (Int (Fbuf));
  488.             Tree_Write_Int (Int (Lbuf));
  489.             Tree_Write_Data (Buf (Fbuf)'Address, Int (Lbuf - Fbuf + 1));
  490.  
  491.             Tree_Write_Int (Flin);
  492.             Tree_Write_Int (Llin);
  493.             Tree_Write_Data (Lins (Flin)'Address, Int (Llin - Flin + 1));
  494.          end;
  495.       end loop;
  496.    end Tree_Write;
  497.  
  498.    --------------------
  499.    -- Write_Location --
  500.    --------------------
  501.  
  502.    procedure Write_Location (P : Source_Ptr) is
  503.    begin
  504.       if P = No_Location then
  505.          Write_Str ("<no location>");
  506.  
  507.       elsif P <= Standard_Location then
  508.          Write_Str ("<standard location>");
  509.  
  510.       else
  511.          Write_Char ('"');
  512.          Write_Name (Reference_Name (Get_Source_File_Index (P)));
  513.          Write_Str (""", line ");
  514.          Write_Int (Int (Get_Line_Number (P)));
  515.          Write_Char (':');
  516.          Write_Int (Int (Get_Column_Number (P)));
  517.       end if;
  518.    end Write_Location;
  519.  
  520.    ----------------------
  521.    -- Write_Time_Stamp --
  522.    ----------------------
  523.  
  524.    procedure Write_Time_Stamp (S : Source_File_Index) is
  525.       T : constant Time_Stamp_Type := Time_Stamp (S);
  526.  
  527.    begin
  528.       Write_Char (T (1));
  529.       Write_Char (T (2));
  530.       Write_Char ('-');
  531.  
  532.       Write_Char (T (3));
  533.       Write_Char (T (4));
  534.       Write_Char ('-');
  535.  
  536.       Write_Char (T (5));
  537.       Write_Char (T (6));
  538.       Write_Char (' ');
  539.  
  540.       Write_Char (T (7));
  541.       Write_Char (T (8));
  542.       Write_Char (':');
  543.  
  544.       Write_Char (T (9));
  545.       Write_Char (T (10));
  546.       Write_Char ('.');
  547.  
  548.       Write_Char (T (11));
  549.       Write_Char (T (12));
  550.    end Write_Time_Stamp;
  551.  
  552.    ----------------------------------------------
  553.    -- Access Subprograms for Source File Table --
  554.    ----------------------------------------------
  555.  
  556.    function File_Name (S : Source_File_Index) return File_Name_Type is
  557.    begin
  558.       return Source_File.Table (S).File_Name;
  559.    end File_Name;
  560.  
  561.    function Full_File_Name (S : Source_File_Index) return File_Name_Type is
  562.    begin
  563.       return Source_File.Table (S).Full_File_Name;
  564.    end Full_File_Name;
  565.  
  566.    function Identifier_Casing (S : Source_File_Index) return Casing_Type is
  567.    begin
  568.       return Source_File.Table (S).Identifier_Casing;
  569.    end Identifier_Casing;
  570.  
  571.    function Instantiation (S : Source_File_Index) return Source_Ptr is
  572.    begin
  573.       return Source_File.Table (S).Instantiation;
  574.    end Instantiation;
  575.  
  576.    function Keyword_Casing (S : Source_File_Index) return Casing_Type is
  577.    begin
  578.       return Source_File.Table (S).Keyword_Casing;
  579.    end Keyword_Casing;
  580.  
  581.    function Line_Offset (S : Source_File_Index) return Int is
  582.    begin
  583.       return Source_File.Table (S).Line_Offset;
  584.    end Line_Offset;
  585.  
  586.    function Num_Source_Lines (S : Source_File_Index) return Nat is
  587.    begin
  588.       return Source_File.Table (S).Num_Source_Lines;
  589.    end Num_Source_Lines;
  590.  
  591.    function Reference_Name (S : Source_File_Index) return File_Name_Type is
  592.    begin
  593.       return Source_File.Table (S).Reference_Name;
  594.    end Reference_Name;
  595.  
  596.    function Source_First (S : Source_File_Index) return Source_Ptr is
  597.    begin
  598.       return Source_File.Table (S).Source_First;
  599.    end Source_First;
  600.  
  601.    function Source_Last (S : Source_File_Index) return Source_Ptr is
  602.    begin
  603.       return Source_File.Table (S).Source_Last;
  604.    end Source_Last;
  605.  
  606.    function Source_Text (S : Source_File_Index) return Source_Buffer_Ptr is
  607.    begin
  608.       return Source_File.Table (S).Source_Text;
  609.    end Source_Text;
  610.  
  611.    function Template (S : Source_File_Index) return Source_File_Index is
  612.    begin
  613.       return Source_File.Table (S).Template;
  614.    end Template;
  615.  
  616.    function Time_Stamp (S : Source_File_Index) return Time_Stamp_Type is
  617.    begin
  618.       return Source_File.Table (S).Time_Stamp;
  619.    end Time_Stamp;
  620.  
  621.    ------------------------------------------
  622.    -- Set Procedures for Source File Table --
  623.    ------------------------------------------
  624.  
  625.    procedure Set_Keyword_Casing (S : Source_File_Index; C : Casing_Type) is
  626.    begin
  627.       Source_File.Table (S).Keyword_Casing := C;
  628.    end Set_Keyword_Casing;
  629.  
  630.    procedure Set_Identifier_Casing (S : Source_File_Index; C : Casing_Type) is
  631.    begin
  632.       Source_File.Table (S).Identifier_Casing := C;
  633.    end Set_Identifier_Casing;
  634.  
  635.    procedure Set_Line_Offset (S : Source_File_Index; V : Int) is
  636.    begin
  637.       Source_File.Table (S).Line_Offset := V;
  638.    end Set_Line_Offset;
  639.  
  640.    procedure Set_Reference_Name (S : Source_File_Index; N : Name_Id) is
  641.    begin
  642.       Source_File.Table (S).Reference_Name := N;
  643.    end Set_Reference_Name;
  644.  
  645. end Sinput;
  646.