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

:Program.    WBReadArgs.mod
:Contents.   ReadArgs() for Workbench arguments
:Author.     Hartmut Goebel [hG]
:Address.    Aufseßplatz 5, D-8500 Nürnberg 40
:Address.    UseNet: hartmut@oberon.nbg.sub.org
:Address.    Z-Netz: hartmut@asn.zer   Fido: 2:246/81.1
:Copyright.  Copyright © 1993 by Hartmut Goebel
:Language.   Oberon
:Translator. Amiga Oberon V3.0
:History.    V1.0, 03 Jan 1993 [hG]
:Date.       03 Jan 1993 17:03:37

(* $StackChk- $NilChk- $RangeChk- $CaseChk- $OvflChk- $ReturnChk- $ClearVars- *)

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

MODULE WBReadArgs;

IMPORT
  d *:= Dos,
  e := Exec,
  icn := Icon,
  Strings,
  wb *:= Workbench,
  y := SYSTEM;

CONST
  (* error codes *)
  okay     *= 0;
  otherErr *= 1;
  noMemory *= 2;
  noIcon   *= 3;
  parsingErr *= 4;
  wrongParam  *= 5;
  templateErr *= 6;

VAR
  error *: INTEGER;

TYPE
  ToolTypes = UNTRACED POINTER TO ARRAY 2 OF e.STRPTR;
  Arguments * = STRUCT
    dobj -: wb.DiskObjectPtr;
    longs: UNTRACED POINTER TO ARRAY OF LONGINT;
  END;

VAR
  dos: d.DosLibraryPtr;

PROCEDURE StrToLong *{dos,-816}(string{1}    : e.STRPTR;
                                VAR value{2} : LONGINT): LONGINT;

(*
******* WBReadArgs/ReadArgs ***********************************
*
*  NAME
*       ReadArgs - parses tool types like Dos.ReadArgs()
*
*  SYNOPSIS
*       ReadArgs (wbarg: wb.WBArg;
*              template: ARRAY OF CHAR;
*          VAR argArray: ARRAY OF y.BYTE;
*              VAR args: Arguments): BOOLEAN;
*
*  FUNCTION
*       Takes the icon associated with the workbench argument and
*       parses its tool types like Dos.ReadArgs().
*
*       The template switches /S, /T, /N and /K are supported, /M and /A
*       are not since they are useless in tool types. Only the first
*       switch of each entry is observed, and the entry will be
*       ignored if this is /M, /A or has no switch.
*
*       Make sure the template is terminated by CHR(0) (each constant
*       string is).
*
*       Do not change the values argArray points to since they just hold
*       then value returned from FindToolType(), if any.
*
*       Use FreeArgs() to free all memory allocated be GetArgs(). You
*       must not reuse args before FreeArgs() has been called.
*
*  NOTES
*       This function is not very smart, so you must follow the
*       restictions above. But they are no handicap for using the same
*       template for Dos.ReadArgs(): just put /S, /T or /N (if any) in
*       front of /K and /M or /A behind.
*
*       Short switch syntax: ["/S"|"/N"|"/T"] ["/K"] ["/M"]["/A"]
*
*  INPUTS
*       wbarg    - workbench argument pointer to be parsed
*       template - template for parsing the tool types
*       argArray - to store the results
*       args     - structure to store internal
*
*  RESULTS
*       args     - contents internal data, args.dobj points to the icon
*
******)

PROCEDURE ReadArgs * (wbarg: wb.WBArg;
                   template: ARRAY OF CHAR;
               VAR argArray: ARRAY OF y.BYTE;
                   VAR args: Arguments): BOOLEAN;
VAR
  argv: UNTRACED POINTER TO ARRAY 7000H OF e.APTR;
  len, cnt: LONGINT;
  acnt, lcnt: INTEGER;
  str, str2: e.STRPTR;
  c : CHAR;
  oldDir: d.FileLockPtr;
BEGIN
  error := okay;
  IF wbarg.name = NIL THEN
    error := otherErr;
  ELSE
    oldDir := d.CurrentDir(wbarg.lock);
    args.dobj := icn.GetDiskObject(wbarg.name^);
    IF args.dobj = NIL THEN
      error := noIcon;
    ELSE
      (* count /N *)
      len := -1; cnt := 0;
      LOOP
        len := Strings.OccursPos(template,"/N",len+1);
        IF len < 0 THEN EXIT; END;
        INC(cnt);
      END;
      IF cnt # 0 THEN
        y.ALLOCATE(args.longs,cnt);
      END;
      IF (args.longs # NIL) OR (cnt = 0) THEN
        argv := y.ADR(argArray);
        len := 0; lcnt := 0; acnt := 0;
        WHILE len < LEN(template) DO
          str := y.ADR(template[len]);
          cnt := 0;
          LOOP
            CASE str[cnt] OF
            CHR(0), "/",  ",": EXIT;
            ELSE
              INC(cnt);
            END;
          END;
          c := str[cnt];
          str[cnt] := CHR(0);
          str2 := icn.FindToolType(args.dobj.toolTypes,str^);
          str[cnt] := c;
          IF c = "/" THEN (* switch *)
            CASE str[cnt+1] OF
            "N": (* numeric *)
                 IF str2 # NIL THEN
                   IF StrToLong(str2,args.longs[lcnt]) < 0 THEN
                     error := wrongParam;
                   ELSE
                     argv[acnt] := y.ADR(args.longs[lcnt]);
                   END;
                 END;
                 INC(lcnt); |
            "K": (* keyword *)
                 IF str2 # NIL THEN argv[acnt] := str2; END; |
            "S": (* switch *)
                 IF str2 # NIL THEN
                   argv[acnt] := d.DOSTRUE;
                 ELSE
                   argv[acnt] := d.DOSFALSE;
                 END; |
            "T": (* toggle *)
                 IF str2 # NIL THEN
                   IF argv[acnt] = d.DOSFALSE THEN
                     argv[acnt] := d.DOSTRUE;
                   ELSE
                     argv[acnt] := d.DOSFALSE;
                   END;
                 END; |
            "M", "A": (* ignore *)
            ELSE
              error := templateErr;
            END;
          END;
          INC(acnt); INC(cnt);
          LOOP
            CASE str[cnt] OF
            CHR(0), ",": EXIT;
            ELSE
              INC(cnt);
            END;
          END;
          INC(len,cnt+1);
        END;
      ELSE
        error := noMemory;
      END; (*args.long *)
    END; (* args.dobj *)
    IF  d.CurrentDir(oldDir) = NIL THEN END;
  END; (* wbarg.name *)
  RETURN error = okay;
END ReadArgs;

(*
******* WBReadArgs/FreeArgs ***********************************
*
*  NAME
*       FreeArgs - free memory used by GetArgs
*
*  SYNOPSIS
*       FreeArgs * (VAR args: Arguments);
*
*  FUNCTION
*       Frees all memory and resources allocated when calling
*       GetArgs().
*
*       args may be used for another call of GetArgs() afterwards.
*
**********)

PROCEDURE FreeArgs * (VAR args: Arguments);
BEGIN
  IF args.dobj # NIL THEN icn.FreeDiskObject(args.dobj) END;
  (* $IFNOT GarbaceCollector *)
    DISPOSE (args.longs);
  (* $ELSE *)
    args.longs := NIL;
  (* $END *)
  args.dobj := NIL;
END FreeArgs;

BEGIN
  dos := d.dos;

END WBReadArgs.
