-- $Id: wc.gnat,v 1.0 2003/06/11 12:11:00 dada Exp $
-- http://dada.perl.it/shootout/
-- Ada 95 code by C.C.

-- Annotated Ada Reference Manual ISO/IEC 8652:1995: http://www.ada-auth.org/

with Interfaces.C, System, Ada.Strings.Fixed, Ada.Text_IO;

procedure Wc is
   package IC renames Interfaces.C;
   function L_Trim (Source : String; Side : Ada.Strings.Trim_End :=
               Ada.Strings.Left) return String renames Ada.Strings.Fixed.Trim;

   package Io is
      type File_Descriptor is new IC.int;       --  STDIN=0, STDOUT=1, STDERR=2
      type Setmode_Flag is new IC.int;
      STDIN       : constant File_Descriptor := 0;
      O_BINARY    : constant Setmode_Flag := 16#8000#;

      function C_Setmode (
               FD       : File_Descriptor;
               Mode     : Setmode_Flag)
            return IC.int;

      function C_Sysread (
               FD       : File_Descriptor;
               Buf      : System.Address;
               NByte    : IC.int)
            return IC.int;
   private
      pragma Import (C, C_Setmode, "_setmode");          --  Microsoft Windows
      pragma Import (C, C_Sysread, "_read");
   end Io;

   Buffer      : String (1 .. 4 * 1024);
   NL, NW, NC  : Natural := 0;
   Inside_Word : Boolean := False;
   C           : Character;
   Last, R     : Integer;
begin
   R := Integer (Io.C_Setmode (Io.STDIN, Io.O_BINARY));  --  Read CR,LF right
   loop
      Last := Integer (Io.C_Sysread (FD => Io.STDIN,
                  Buf => Buffer (1)'Address, NByte => Buffer'Length));
      exit when Last <= 0;
      NC := NC + Last;
      for K in Buffer'First .. Last loop
         C := Buffer (K);
         if C = ASCII.LF then
            NL := NL + 1;
         end if;
         if C = ' ' or C = ASCII.CR or C = ASCII.LF or C = ASCII.HT then
            Inside_Word := False;
         elsif not Inside_Word then
            Inside_Word := True;
            NW := NW + 1;
         end if;
      end loop;
   end loop;
   Ada.Text_IO.Put_Line (L_Trim (Natural'Image (NL)) & Natural'Image (NW) &
            Natural'Image (NC));
end Wc;
   --  The "Ada.Streams.Stream_IO.Read (File, Item, Last)" procedure can't
   --  read from STDIN: can't associate Standard Input with File parameter.
   --  GNAT's Interfaces.C_Streams.fread function isn't from ISO/IEC 8652:1995.