TEAM-ADA Archives

Team Ada: Ada Programming Language Advocacy


Options: Use Classic View

Use Monospaced Font
Show Text Part by Default
Show All Mail Headers

Topic: [<< First] [< Prev] [Next >] [Last >>]

Print Reply
"Carlisle, Martin" <[log in to unmask]>
Thu, 14 Oct 1999 09:16:26 -0600
text/plain (225 lines)
After the signature block, please find the new AdaGIDe statistics counter
source (in Ada) that counts semicolons, lines, and other useful things.
Feel free to contribute new statistics.

Note in particular that semicolons inside character literals, strings and
comments are not counted.

This will appear in the next release of AdaGIDE (available at
in a day or so.


Martin C. Carlisle,
Asst Prof of Computer Science
US Air Force Academy
[log in to unmask]
DISCLAIMER: The content of this message contains the author's opinions, and
does not reflect the policy of the US Air Force Academy or US Government.

--  Description : compute Ada statistics
--  By: Dr. Martin C. Carlisle
--  Original Copyright (C) 1999 Martin C. Carlisle
--  This is a derivative work by:
--     US Air Force Academy Department of Computer Science
-- AdaGIDE is free software; you can redistribute it and/or
-- modify it under terms of the GNU General Public License
-- as published by the Free Software Foundation and modified
-- below; either version 2, or (at your option) any later version.
-- AdaGIDE is distributed in the hope that it will be useful,
-- but WITHOUT ANY WARRANTY; without even the implied warranty
-- See the GNU General Public License for more details.
-- You should have received a copy of the GNU General Public
-- License distributed with AdaGIDE; see file COPYING.HTML.  If
-- not, write to the Free Software Foundation, 59 Temple Place,
-- Suite 330, Boston, MA 02111-1307, USA.

with Ada.Text_Io;
use Ada.Text_Io;
with Ada.Integer_Text_Io;
use Ada.Integer_Text_Io;
with Ada.Command_Line;
use Ada.Command_Line;
with Ada.Strings.Unbounded;
with Ada.Strings.Fixed;
procedure Count is
   procedure Usage is
      Put_Line("Usage: " & Command_Name & " file1 [file2...]");
   end Usage;

   -- Get a line, no matter how long it is.
   -- Could use recursion here, but instead I'm using
   -- an unbounded string
   function Get_Line (
         File : File_Type )
     return String is
      Part : String (1 .. 256);
      Last : Natural;
      Long : Ada.Strings.Unbounded.Unbounded_String;
      use type Ada.Strings.Unbounded.Unbounded_String;
      Get_Line(File, Part, Last);
      if Last = Part'Last then
         Long := Ada.Strings.Unbounded.To_Unbounded_String(Part);
         while Last=Part'Last loop
            Long := Long & Part(1..Last);
         end loop;
         return Ada.Strings.Unbounded.To_String(Long);
         return Part(1..Last);
      end if;
   end Get_Line;

   procedure Process_File (
         Name : in     String ) is
      Semicolons                  : Natural   := 0;
      Lines_Ending_In_Semicolon   : Natural   := 0;
      Lines                       : Natural   := 0;
      Blank_Lines                 : Natural   := 0;
      Comment_Lines               : Natural   := 0;
      File                        : File_Type;
      Put_Line("FILE: " & Name);
         File => File,
         Name => Name,
         Mode => In_File);
      while not End_Of_File(File) loop
            Line             : String  := Get_Line (File);
            First_Char       : Natural := Ada.Strings.Fixed.Index_Non_Blank
            Comment_Location : Natural := Ada.Strings.Fixed.Index (Source
              => Line, Pattern => "--");
            Lines := Lines + 1;
            if First_Char=0 then
               Blank_Lines := Blank_Lines + 1;
            elsif First_Char = Comment_Location then
               Comment_Lines := Comment_Lines + 1;
               -- we must use a state machine to walk through the string
               -- if we're here we know that we have neither a comment
               -- nor a blank line
               -- count semicolons if not inside strings, stop at comment
                  type State is
                  Current_State  : State   := Code;
                  I              : Natural;
                  Last_Character : Natural;
                  I := Line'First;
                  while I <= Line'Last loop
                     case Line(I) is
                        when ''' =>
                           -- check for character literal
                           if Current_State/=In_String then
                              Current_State := Code; -- no longer in minus
                              if i+2<=Line'Last and then
                                 Line(i+2) = ''' then
                                 i:=i+2; -- go past char literal
                              end if;
                           end if;
                        when '-' =>
                           if Current_State=Code then
                              Current_State := Minus;
                           elsif Current_State = Minus then
                              I := I - 1; -- see below
                              exit; -- start of comment
                           end if;
                        when '"' =>
                           if Current_State=In_String then
                              Current_State := Code;
                              Current_State := In_String;
                           end if;
                        when ';' =>
                           if Current_State /= In_String then
                              Semicolons := Semicolons + 1;
                           end if;
                        when others =>
                     end case;
                     I := I + 1;
                  end loop;
                  -- at this point, i is either one past end of line
                  -- or at the first - of a comment
                  -- in either case, check if semicolon is last
                  -- non-blank of Line(Line'First..i-1)
                  -- note we know line has at least one non-blank
                  Last_Character := Ada.Strings.Fixed.Index_Non_Blank(
                    Source => Line (Line'First .. I - 1),
                    Going  => Ada.Strings.Backward);
                  if Line(Last_Character) = ';' then
                     Lines_Ending_In_Semicolon :=
                        + 1;
                  end if;
            end if;
      end loop;

      -- now that we have looped through whole file, print out the stats
      Put("Total Lines:                 ");
      Put("Lines ending w/semicolon:    ");
      Put("Blank Lines:                 ");
      Put("Comment Lines:               ");
      Put("Non-blank non-comment lines: ");
      Put("Semicolons:                  ");
      when Name_Error =>
         Put_Line("File not found");
      when Status_Error|Use_Error =>
         Put_Line("Error reading file");
   end Process_File;
   Put_Line("Ada Statistics Counter 1.0");
   Put_Line("October 14, 1999");
   Put_Line("By: Martin C. Carlisle");
   Put_Line("[log in to unmask]");

   if Argument_Count < 1 then
   end if;

   for i in 1..Argument_Count loop
   end loop;
end Count;