* === rx.asm ===========================================================
*
* Copyright (c) 1986, 1987 William S. Hawes (All Rights Reserved)
*
* ======================================================================
*
* Launches REXX programs from the CLI.  The command line (in A0) is passed
* to the REXX interpreter as a command.
*
* N.B. Due to the command-line parsing mechanism of the CLI, the command
* cannot include semicolons (;) unless they are enclosed in double quotes.

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

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

         XREF     _AbsExecBase

         ; EXEC library routines

         XLIB     AllocMem
         XLIB     CloseLibrary
         XLIB     FindPort
         XLIB     FindTask
         XLIB     Forbid
         XLIB     FreeMem
         XLIB     GetMsg
         XLIB     OpenLibrary
         XLIB     Permit
         XLIB     PutMsg
         XLIB     WaitPort

         XLIB     Output
         XLIB     Write

         ; Command string is in (A0,D0)

start:   movea.l  _AbsExecBase,a6      ; EXEC library base
         movea.l  a0,a3                ; command string
         move.l   d0,d3                ; initial length (always > 0)

         ; Trim trailing blanks and control characters from command line 

         lea      0(a3,d3.l),a1        ; end of line
         bra.s    2$                   ; jump in

1$:      cmp.b    #' ',-(a1)           ; > blank?
         bhi.s    3$                   ; yes
2$:      dbf      d3,1$                ; loop back

3$:      addq.w   #1,d3                ; restore length
         clr.b    0(a3,d3.w)           ; a null

         ; Find us

         suba.l   a1,a1
         CALLSYS  FindTask             ; D0=task id
         movea.l  d0,a4                ; save it

         ; Open the DOS library

         lea      DOSLib(pc),a1
         moveq    #LIBRARY_VERSION,d0
         CALLSYS  OpenLibrary
         move.l   d0,d5                ; a DOS?
         beq      Exit                 ; no??

         ; Forbid task switching while we send the packet

         CALLSYS  Forbid

         ; Look for the REXX public message port.

         lea      REXX(pc),a1          ; REXX name (string structure)
         CALLSYS  FindPort             ; return: D0=port
         move.l   d0,d2                ; port found?
         beq      Error1               ; no -- error

         ; Open the REXX Systems library

         lea      RXSLib(pc),a1        ; library name
         moveq    #RXSVERS,d0          ; version
         CALLSYS  OpenLibrary
         tst.l    d0                   ; opened?
         beq      Error2               ; no
         movea.l  d0,a5

         ; Allocate a message packet structure.

         lea      pr_MsgPort(a4),a0    ; our processid
         movea.l  d2,a1                ; REXX port
         move.l   LN_NAME(a1),d0       ; Host Address
         lea      FileExt(pc),a1       ; file extension
         exg      a5,a6
         CALLSYS  CreateRexxMsg        ; return: D0=A0=packet
         exg      a5,a6
         beq.s    Error3               ; allocation failure ...

         ; Fill in the message packet

         movea.l  a0,a2                ; save packet
         move.l   #RXCOMM,ACTION(a0)   ; command code
         move.l   a3,ARG0(a0)          ; command string
         moveq    #1,d0                ; one string
         moveq    #0,d1                ; string conversion
         exg      a5,a6
         CALLSYS  FillRexxMsg          ; D0=boolean
         exg      a5,a6
         beq.s    Error4               ; ... failure

         ; Send off the message packet

         movea.l  d2,a0                ; REXX public port
         movea.l  a2,a1                ; message packet
         CALLSYS  PutMsg               ; send it off

         ; Wait for the packet to return.  Task switching is reenabled.

         lea      pr_MsgPort(a4),a0
         CALLSYS  WaitPort
         lea      pr_MsgPort(a4),a0
         CALLSYS  GetMsg               ; get the message
         move.l   RESULT1(a2),d6       ; return code
         bra.s    Clean3

         ; Error ... REXX port not found.

Error1:  lea      ErrMsg1(pc),a0
         moveq    #ERRLEN1,d0
         bsr      WriteMsg
         bra.s    CloseDOS

         ; Error ... couldn't open the library.

Error2   lea      ErrMsg2(pc),a0
         moveq    #ERRLEN2,d0
         bsr      WriteMsg
         bra.s    CloseDOS

         ; Error ... couldn't allocate the message.

Error3   lea      ErrMsg3(pc),a0
         moveq    #ERRLEN3,d0
         bsr      WriteMsg
         bra.s    CloseREXX

         ; Error ... couldn't allocate the command string

Error4   lea      ErrMsg3(pc),a0
         moveq    #ERRLEN3,d0
         bsr      WriteMsg
         bra.s    ReleaseMsg

         ; Cleanup operations

Clean3:  movea.l  a2,a0                ; message
         moveq    #1,d0                ; one string
         exg      a5,a6
         CALLSYS  ClearRexxMsg         ; recycle it
         exg      a5,a6

ReleaseMsg
         movea.l  a2,a0                ; message packet
         exg      a5,a6                ; EXEC=>A5 , REXX=>A6
         CALLSYS  DeleteRexxMsg        ; release it
         exg      a5,a6                ; REXX=>A5 , EXEC=>A6

         ; Close the REXX library

CloseREXX:
         movea.l  a5,a1                ; REXX system library
         CALLSYS  CloseLibrary

         ; Close the DOS library

CloseDOS:
         movea.l  d5,a1                ; DOS library
         CALLSYS  CloseLibrary
         CALLSYS  Permit

Exit:    move.l   d6,d0                ; load return code
         rts

* Display an error message
WriteMsg:
         movem.l  d2/d3,-(sp)
         move.l   a0,d2
         move.l   d0,d3
         exg      d5,a6
         CALLSYS  Output
         move.l   d0,d1
         CALLSYS  Write
         exg      d5,a6
         movem.l  (sp)+,d2/d3
         rts

         ; String data

DOSLib   dc.b     'dos.library',0
RXSLib   RXSNAME                       ; library name
REXX     dc.b     'REXX',0             ; REXX port name
FileExt  dc.b     'rexx',0             ; file extension

ErrMsg1  dc.b     'REXX port not found',10
ERRLEN1  EQU      *-ErrMsg1
ErrMsg2  dc.b     'File rexxsyslib.library not found',10
ERRLEN2  EQU      *-ErrMsg2
ErrMsg3  dc.b     'Allocation failure',10
ERRLEN3  EQU      *-ErrMsg3
         CNOP     0,2

         END
