(*
 *  OAvail - A simple CLI command that displays stats about memory.
 *           the Amiga's memory.
 *
 *  Written 1990 by Peter Fröhlich of Nephthys Software.
 *
 *  OAvail is hereby released in the Public Domain pool. Humpty says:
 *  "Do watya like..." with this source code that is.
 *
 *  This is my FIRST Oberon program, so this code might look weird
 *  to some of the Oberon freaks out there. Please feel free to
 *  post any comments or improvements to this program to the net.
 *
 *  My address: P.FROEHLICH@MUSIKBOX.ZER
 *
 *  Thanx...
 *)

(* !!! Use SMALLCODE SMALLDATA !!! *)

MODULE OAvail;

IMPORT
  a   : ARP,
  e   : Exec,
  sys : SYSTEM;

CONST
  Title = "\[33;1mOAvail\[m V1.0 by P.Froehlich of Nephthys Software\n\[4mType   Availiable    In-Use   Maximum   Largest\[m";
  Chip  = "CHIP";
  Fast  = "FAST";
  Pub   = "PUBLIC";
  Fmt   = "%-6.6s  %9.9ld %9.9ld %9.9ld %9.9ld\n";

VAR
  li : LONGINT;              (* Fuer Rueckgabewerte von arp.library *)
  totalchip,
  totalfast  : LONGINT;      (* Summen der MemHeader *)
  totalmem   : LONGINT;      (* Groesse des aktuellen MemHeaders *)

  data : ARRAY 5 OF LONGINT; (* Fuer arp.library Printf() *)



(*
 * PROCEDURE NextNode:
 *   e.NodePtr := NextNode (e.NodePtr);
 *)
PROCEDURE NextNode(n: e.NodePtr): e.NodePtr;
VAR
  p : e.NodePtr; (* Hilfspointer *)

BEGIN
  p := n.succ; (* p := Pointer auf NAECHSTEN Knoten *)
  IF (p.succ = 0) THEN
    RETURN NIL;
  ELSE
    RETURN p;
  END; (* IF *)

(*
 * Ist das besserer Stil ?
 * IF (p.succ = 0) THEN RETURN NIL ELSE RETURN p END; (* IF *)
 *)
END NextNode;


(*
 *
 *
 *)

PROCEDURE GetTotalMem(attributes: INTEGER): LONGINT;
VAR
  np : e.NodePtr;            (* Zeiger auf MemHeader *)
  ml : e.List;               (* Nimmt e.exec.memList auf *)
  mhp : e.MemHeaderPtr;      (* Um auf Felder im MemHeader zugreifen zu
                                koennen *)
  totalmem : LONGINT;        (* Größe des gesamten Speichers mit den
                                angegebenen Attributen *)
  thismem : LONGINT;         (* Größe des aktuellen MemHeaders *)

BEGIN
  totalmem := 0;

  ml := e.exec.memList;
  np := ml.head;
  mhp := sys.VAL(LONGINT,np); (* Wie macht man das sonst ? *)

  REPEAT
    thismem := mhp.upper - mhp.lower; (* Groesse des aktuellen MemHeaders *)

    IF (attributes IN mhp.attributes) THEN
      INC(totalmem,thismem); (* Falls die Attribute übereinstimmen wird
                                dieser Memheader zu totalmem addiert. *)
    END; (* IF *)

    np := NextNode(np);
    mhp := sys.VAL(LONGINT,np);
  UNTIL (np = NIL);

  RETURN totalmem;
END GetTotalMem;




(*
 *
 *)

BEGIN
  totalchip := GetTotalMem(e.chip);
  totalfast := GetTotalMem(e.fast);

  li := a.Puts(Title);

  (* Fill array with values for MEMF_CHIP *)
  data[0] := sys.ADR(Chip);
  data[1] := e.AvailMem(LONGSET{e.chip});
  data[3] := totalchip;
  data[2] := data[3]-data[1];
  data[4] := e.AvailMem(LONGSET{e.chip,e.largest});
  li := a.Printf(Fmt,sys.ADR(data[0]));

  (* Fill array with values for MEMF_FAST *)
  data[0] := sys.ADR(Fast);
  data[1] := e.AvailMem(LONGSET{e.fast});
  data[3] := totalfast;
  data[2] := data[3]-data[1];
  data[4] := e.AvailMem(LONGSET{e.fast,e.largest});
  li := a.Printf(Fmt,sys.ADR(data[0]));

  (* Fill array with values for MEMF_PUBLIC *)
  data[0] := sys.ADR(Pub);
  data[1] := e.AvailMem(LONGSET{e.public});
  data[3] := totalfast+totalchip;
  data[2] := data[3]-data[1];
  data[4] := e.AvailMem(LONGSET{e.public,e.largest});
  li := a.Printf(Fmt,sys.ADR(data[0]));
END OAvail.

