File : find_marks.adb


-- Find_Marks (main procedure)
--
-- Finds "marks" in source-code files, for use in "assertions" to
-- guide and control the Bound-T Execution Time Analyser when analysing
-- the target program generated from those source-code files.
--
-- This program is applied to one or more named files, in the form:
--
--     find_marks [-opts] file [ [-opts] file ...] >output-mark-file
--
-- The optional options (-opts) before an input file name are used to
-- define the type of the following files (= the programming language).
-- If no options are given, or the option -auto, the file-name suffix
-- is used.
--
-- See the Bound-T documentation (option "-mark") for the format of the
-- output-mark-file. On the input side, the format of the marks in the
-- source-code files is whatever this program (find_marks) accepts; see
-- the child packages of the Marks package.
--
-- Copyright (c) 2009 Tidorum Ltd.
--
-- This file is part of Find_Marks.
--
-- Find_Marks is free software: you can redistribute it and/or modify
-- it under the terms of the GNU General Public License as published by
-- the Free Software Foundation, either version 3 of the License, or
-- (at your option) any later version.
--
-- This program is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty of
-- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-- GNU General Public License for more details.
--
-- You should have received a copy of the GNU General Public License
-- along with this program.  If not, see <http://www.gnu.org/licenses/>.


with Ada.Command_Line;
with Ada.Strings;
with Ada.Strings.Fixed;
with Ada.Text_IO;
with Marks;
with Marks.Formats;


procedure Find_Marks
is

   use Ada.Command_Line;
   use Ada.Strings;
   use Ada.Strings.Fixed;
   use Ada.Text_IO;


   Max_Line_Length : constant := 2_000;
   --
   -- Maximum length of a source-code line (input line).


   procedure Scan (Source : in File_Type)
   --
   -- Finds the marks in the given Source file.
   --
   is

      Text : String (1 .. Max_Line_Length);
      Last : Natural;
      -- An input line.

      Number : Positive_Count;
      -- The number of the line.

   begin

      while not End_Of_File (Source) loop

         Number := Line (Source);

         Get_Line (Source, Text, Last);

         if Col (Source) = 1 then
            -- Good, we read all of a line.

            Marks.Scan (
               Line   => Trim (Text(1 .. Last), Both),
               Number => Number);

         else

            Marks.Report_Error (
                 "Source-file line is too long (over"
               & Natural'Image (Text'Length)
               & " characters).");

         end if;

      end loop;

   exception

   when Device_Error =>

      Marks.Report_Error ("Cannot read, perhaps not a text file.");

   end Scan;


   procedure Scan (File_Name : in String)
   --
   -- Finds the marks in the file by the given Name.
   --
   is

      File : File_Type;
      -- The file named File_Name.

   begin

      Open (
         File => File,
         Name => File_Name,
         Mode => In_File);

      Marks.Define_File (Name => File_Name);

      Scan (Source => File);

      Marks.Note_End_Of_File;

      Close (File);

   exception

   when Name_Error =>

      Put_Line (Standard_Error,
         File_Name & ":Cannot find this file.");

      if Is_Open (File) then

         Close (File);

      end if;

   when Use_Error =>

      Put_Line (Standard_Error,
         File_Name & ":Cannot open this file.");

      if Is_Open (File) then

         Close (File);

      end if;

   end Scan;


   procedure Handle_Argument (Arg : in String)
   --
   -- Handles the command-line arguments in sequence.
   --
   is
   begin

      if Arg(Arg'First) = '-' then
         -- This is an option.

         Marks.Note_Option (Arg);

      else

         Scan (File_Name => Arg);

      end if;

   end Handle_Argument;


begin  -- Find_Marks

   for A in 1 .. Argument_Count loop

      Handle_Argument (Argument (A));

   end loop;

end Find_Marks;