(* The Great Win32 Language Shootout http://dada.perl.it/shootout/

   contributed by Isaac Gouy (Modula2 novice)

   To build: xc =m wc
   To run:   wc < input.txt
*)

MODULE Wc;
<* m2extensions + *>

FROM SRawIO IMPORT Read;
FROM SIOResult IMPORT ReadResult, wrongFormat;
FROM SYSTEM IMPORT ADR, FILL;
FROM STextIO IMPORT WriteLn;
FROM SWholeIO IMPORT WriteCard;

CONST
   buffer_size = 4096;
   LF = CHR(10);
   CR = CHR(13);
   TAB = CHR(9);
   Space = CHR(32);
   Null = CHR(0);


TYPE Buffer_Type = ARRAY [1..buffer_size] OF CHAR;


PROCEDURE Fill(VAR buf: Buffer_Type);
   VAR i: INTEGER;
BEGIN
   (* Clear the buffer *)
   FILL( ADR(buf), Null, buffer_size );

   (* Raw read into the buffer *)
   Read(buf);

   IF ReadResult() = wrongFormat THEN
      (* ignore LF if it's followed by end of input *)
      i := LENGTH(buf);
      IF (i > 0) AND (buf[i] = LF) THEN
         buf[i] := Null;
      END;
   END;
END Fill;


VAR
   nc, nl, nw: CARDINAL;
   i, read_length: CARDINAL;
   buf: Buffer_Type;
   c: CHAR;
   insideWord: BOOLEAN;

BEGIN
   insideWord := FALSE;	
   REPEAT
      Fill(buf);

      read_length := LENGTH(buf);	
      INC(nc, read_length);	
      FOR i := 1 TO read_length DO
         c := buf[i];
         IF c = LF THEN INC(nl); END;	
         IF (c = Space) OR (c = LF) OR (c = TAB) OR (c = CR) THEN
            insideWord := FALSE;	
         ELSIF NOT insideWord THEN
            insideWord := TRUE;	
            INC(nw);
         END;
      END;
   UNTIL read_length<1;

   WriteCard(nl,1); WriteCard(nw,0); WriteCard(nc,0); WriteLn;
END Wc.