* === rexxtest.asm =====================================================
*
* Copyright (c) 1986, 1987, 1988 William S. Hawes (All Rights Reserved)
*
* ======================================================================
* Test driver for REXX interpreter (called as a stand-alone).  Prompts
* repeatedly for command strings until a null string is entered.  Commands
* are passed to the interpreter with the specified flag bits set.
*
* Usage: rexxtest [-r] [-s] [-t]
*   -r requests a result string with the RXFB_RESULT bit
*   -s indicates a string file RXFB_STRING bit
*   -t requests command tokenization with the RXFB_TOKEN bit

         INCLUDE  "rexx/storage.i"
         INCLUDE  "rexx/rxslib.i"
         INCLUDE  "rexx/errors.i"

         INCLUDE  "libraries/dos.i"
         INCLUDE  "libraries/dosextens.i"

         IFND     EXEC_EXECBASE_I
ThisTask EQU      276
         ENDC

         XREF     _AbsExecBase

         ; DOS library functions

         XLIB     Write

         ; EXEC library routines

         XLIB     AllocMem
         XLIB     CloseLibrary
         XLIB     FindPort
         XLIB     FindTask
         XLIB     FreeMem
         XLIB     OpenLibrary
         XLIB     RawDoFmt

STACKBF  EQU      128
start    movea.l  _AbsExecBase,a6
         movea.l  ThisTask(a6),a4      ; our task
         lea      -STACKBF(sp),sp      ; buffer area

         moveq    #20,d6               ; load error
         moveq    #0,d7                ; clear flags
         bra.s    4$                   ; jump in

1$:      move.b   (a0)+,d1             ; test character
         tst.b    d2                   ; option?
         bne.s    2$                   ; yes
         cmpi.b   #'-',d1              ; option switch?
         seq      d2                   ; ... set flag
         bra.s    5$

2$:      bclr     #5,d1                ; UPPERcase
         moveq    #RXFB_RESULT,d2      ; load flag bit
         subi.b   #'R',d1              ; string file?
         beq.s    3$                   ; yes

         moveq    #RXFB_STRING,d2      ; load flag bit
         subq.b   #'S'-'R',d1          ; string file?
         beq.s    3$                   ; yes

         moveq    #RXFB_TOKEN,d2       ; load flag bit
         subq.b   #'T'-'S',d1          ; tokenize?
         bne.s    4$                   ; no

3$:      bset     d2,d7                ; set flag
4$:      moveq    #0,d2                ; clear flag

5$:      dbf      d0,1$                ; loop back

         ; Open the DOS library

         lea      DOSLib(pc),a1
         moveq    #0,d0                ; any version
         CALLSYS  OpenLibrary
         move.l   d0,d5

         ; Open the REXX System Library

         lea      RXSLib(pc),a1        ; library name
         moveq    #0,d0                ; any version
         CALLSYS  OpenLibrary
         tst.l    d0                   ; opened ok?
         beq      Exit                 ; no -- error
         movea.l  d0,a5

         ; Allocate the RexxTask structure

         move.l   #rt_SIZEOF,d0
         move.l   #MEMQUICK,d1
         CALLSYS  AllocMem
         tst.l    d0                   ; success?
         beq      CloseREXX            ; no
         movea.l  d0,a3

         ; Allocate a message packet structure.

         suba.l   a0,a0                ; no replyport
         suba.l   a1,a1                ; no extension
         moveq    #0,d0                ; no host address
         exg      a5,a6
         CALLSYS  CreateRexxMsg        ; D0=A0=message
         exg      a5,a6
         beq      FreeTaskBlock

         movea.l  d0,a2                ; save message packet
         move.l   a3,rm_TaskBlock(a2)
         move.l   a5,rm_LibBase(a2)
         move.l   #RXCOMM,ACTION(a2)   ; action code
         or.l     d7,ACTION(a2)        ; OR in flags

         ; Prompt for a command string

Begin    lea      prompt(pc),a0        ; prompt string
         bsr      WriteFmt

         ; Read the command string.

         movea.l  pr_CIS(a4),a0        ; input stream
         movea.l  sp,a1                ; buffer
         move.l   #STACKBF,d0          ; maximum length
         exg      a5,a6
         CALLSYS  DOSRead              ; D0=length
         subq.l   #1,d0                ; remove 'newline'
         ble      AllDone              ; null entry -- exit

         ; Package it as an argstring ...

         movea.l  sp,a0                ; command
         CALLSYS  CreateArgstring      ; D0=A0=argstring
         move.l   d0,ARG0(a2)          ; install the command

         ; Clear the RexxTask structure

         movea.l  a3,a0
         move.l   #rt_SIZEOF,d0        ; total size
         CALLSYS  ClearMem             ; (A0 preserved)
         exg      a5,a6

         ; See if the public REXX port is open.  The public port is not
         ; required for stand-alone operation, but external programs can't
         ; be called unless it is available ...

         movea.l  rl_REXX(a6),a1       ; REXX name (string structure)
         addq.l   #ra_Buff,a1          ; name string
         CALLSYS  FindPort             ; D0=port
         move.l   d0,rt_RexxPort(a3)   ; public port address

         ; Call the interpreter.

         movea.l  a3,a0                ; global data structure
         movea.l  a2,a1                ; message packet
         exg      a5,a6
         CALLSYS  Rexx                 ; D0=error  A0=result
         exg      a5,a6
         move.l   a0,d6                ; result string/reason code
         move.l   d0,d4                ; error level

         ; Print the returned results ...

         lea      result(pc),a0        ; result format
         move.l   d6,-(sp)             ; result string/reason
         move.l   d4,-(sp)             ; error level
         beq.s    Display

         ; An error ... print the reason code.

Reason   lea      reason(pc),a0        ; error format
         moveq    #0,d6                ; no result

Display  movea.l  sp,a1                ; data stream
         bsr      WriteFmt
         addq.l   #8,sp

         ; Delete the packet and command string

CleanUp  exg      a5,a6
         movea.l  d6,a0                ; result string
         CALLSYS  DeleteArgstring      ; recycle it (may be NULL)

         movea.l  ARG0(a2),a0          ; command string
         CALLSYS  DeleteArgstring      ; recycle it
         exg      a5,a6
         bra      Begin                ; loop back

         ; Release allocated structures and close the REXX library.

AllDone  movea.l  a2,a0                ; message packet
         CALLSYS  DeleteRexxMsg        ; release it
         exg      a5,a6

FreeTaskBlock
         move.l   #rt_SIZEOF,d0        ; structure size
         movea.l  a3,a1
         CALLSYS  FreeMem
         moveq    #0,d6                ; clear error

         ; CLose the REXX library

CloseREXX
         movea.l  a5,a1
         CALLSYS  CloseLibrary

Exit     movea.l  d5,a1                ; Close the DOS library
         CALLSYS  CloseLibrary

         move.l   d6,d0                ; return code
         lea      STACKBF(sp),sp
         rts

* ==========================     WriteFmt     ==========================
* Registers:   A0 -- format string
*              A1 -- data stream
*              D0 -- filehandle
WriteFmt
         movem.l  d2/d3/a2/a3/a6,-(sp)
         link     a5,#-256
         move.l   sp,d2                ; save buffer
         clr.l    -(sp)                ; character count

         lea      PushChar(pc),a2      ; insertion function
         movea.l  sp,a3                ; pointer
         CALLSYS  RawDoFmt             ; (A3 preserved)

         move.l   pr_COS(a4),d1        ; output stream
         move.l   (sp)+,d3             ; pop count
         movea.l  d5,a6
         CALLSYS  Write

         unlk     a5
         movem.l  (sp)+,d2/d3/a2/a3/a6
         rts

PushChar move.l   (a3),d1              ; load count
         cmpi.w   #256-1,d1            ; buffer full?
         bge.s    1$                   ; yes
         addq.l   #1,(a3)              ; bump count

1$:      move.b   d0,4(a3,d1.l)        ; install it
         rts

         ; String constants

DOSLib   dc.b     'dos.library',0      ; DOS library
RXSLib   RXSNAME                       ; REXX library

prompt   dc.b     'RX> ',0
result   dc.b     'RC=%ld/%s ',10,0
reason   dc.b     'RC=%ld/%ld',10,0

         END
