(*************************************************************************

:Program.    XSum2.mod
:Contents.   sums up all bytes in a compressed or uncompressed file
:Contents.   without reading the whole file at once into mem
:Author.     Hartmut Goebel [hG] (ported to Oberon)
:Language.   Oberon
:Translator. Amiga Oberon V2.14
:History.    V0.9, 09 Jan 1992 Hartmut Goebel [hG]
:History.    V1.0, 11 Jul 1992 [hG] ·now more Oberon-like :-)
:Date.       27 Jul 1992 12:19:31

*************************************************************************)

(* This is a typical read-and-process xpk application. Try it out... XSum a
 * file, then compress it and XSum it again. The result should be the same.
 *)

MODULE XSum2;

IMPORT
  io,
  arg := Arguments,
  e   := Exec,
  ol  := OberonLib,
  s   := SYSTEM,
  u   := Utility,
  xpk := XpkMaster;

VAR
  len, sum, i: LONGINT;
  outBuf: POINTER TO ARRAY MAX(LONGINT)-1 OF CHAR;
  errBuf: ARRAY xpk.errMsgSize+1 OF CHAR;
  xfh: xpk.XpkFH;
  Arg: e.STRING;

PROCEDURE end(text: ARRAY OF CHAR);
BEGIN
  io.WriteString(text); io.WriteLn;
  HALT(10);
END end;


BEGIN
  sum := 0; i := 0;

  IF arg.NumArgs() # 1 THEN end("Usage: XSum2 <filename>"); END;
  arg.GetArg(1,Arg);

  IF 0 # xpk.OpenTags(xfh,
           xpk.inName,      s.ADR(Arg),      (* The file name to be read              *)
           xpk.getError,    s.ADR(errBuf),   (* A pointer to the error message buffer *)
           xpk.passThru,    e.true,          (* Will pass through uncompressed data   *)
           u.done)
  THEN end(errBuf); END;

  ol.New(outBuf,xfh.fib.nLen);
  IF outBuf = NIL THEN end("Out of memory"); END;

  len := xpk.Read(xfh, outBuf^, xpk.lenOneChunk);

  WHILE len > 0 DO
    i := 0;
    REPEAT
      INC(sum,ORD(outBuf[i]));
      INC(i);
    UNTIL i = len;
    len := xpk.Read(xfh, outBuf^, xpk.lenOneChunk);
  END;

  IF (xpk.Close(xfh) #0) OR (len # 0) THEN end(errBuf); END;
  io.WriteInt(sum,0); io.WriteLn;

CLOSE
  ol.Dispose(outBuf);

END XSum2.
