#include <exec/types.h>
#include <exec/ports.h>
#include "rexx.h"

extern struct RexxMsg	*CreateRexxMsg();
extern STRPTR		CreateArgstring();
extern struct MsgPort	*FindPort(),*CreatePort();

static struct MsgPort	*RexxPort = 0L;

/*--------------------------------------------------------*/
/*                   Meinen Port öffnen                   */
/*--------------------------------------------------------*/
struct MsgPort *SetupMyPort(Name,Extension)
{
   struct MsgPort *Port;

  RexxPort = FindPort("REXX");
  if (!RexxPort) return(0L);

  Forbid();
  {
    /*     Erst mal sehen, ob wir schon irgendwo laufen?      */
    /*             (Multitasking macht's möglich)             */
    if (FindPort(Name))
    {
      Permit();
      return(NULL);
    }

    /*                      Port öffnen                       */
    Port = CreatePort(Name,0L);
  }
  Permit();

  return(Port);
}

/*--------------------------------------------------------*/
/*                     Makro starten                      */
/*--------------------------------------------------------*/
int RX(Makro,MyPort,Extension)
char		*Makro;
struct MsgPort	*MyPort;
char		*Extension;
{
  struct RexxMsg *RxComMsg;

/*      Ich brauche ein Message Packet für das Makro      */
  if ( (RxComMsg =
        CreateRexxMsg(MyPort,Extension,MyPort->mp_Node.ln_Name))
       == NULL)  return(1);

/*        Installiere ein ArgString in der Message        */
  if ((RxComMsg->rm_Args[0] = CreateArgstring(Makro,strlen(Makro)))==NULL)
  {
    DeleteRexxMsg(RxComMsg);
    return(1);
  }

/*      Dies ist ein COMMAND, nicht eine FUNCTION...      */
  RxComMsg->rm_Action = RXCOMM;

/*                        Und los!                        */
  PutMsg(RexxPort,RxComMsg);

/*                        Fertig!                         */
  return(0);
}

/*--------------------------------------------------------*/
void FreeRexxCommand(RxMsg)
struct RexxMsg *RxMsg;
{
/*            Den ArgString wieder freigenben             */
  DeleteArgstring(RxMsg->rm_Args[0]);

/*           Die Rexx-Message wieder freigeben            */
  DeleteRexxMsg(RxMsg);
}

/*--------------------------------------------------------*/
/*   Gib eine RexxMsg zurück, wobei die richtigen Codes   */
/*                   ausgefüllt werden.                   */
/*                                                        */
/* Falls ein RESULT angefordert wurde, muß ein ArgString  */
/*    allokiert und mit einem Ergebnis besetzt werden.    */
/*        Dieser ArgString muß in Result2 stehen.         */
/*                                                        */
/*   Wenn primary != 0 und secondary != 0, dann ist ein   */
/*  Fehler aufgetreten. In primary steht dann der Grad    */
/*         und in secondary der REXX Fehler Code.         */
/*                                                        */
/*    Wenn primary != 0, aber secondary == 0, dann ist    */
/*                primary ein Return Code.                */
/*--------------------------------------------------------*/
void ReplyRexxCommand(RxMsg,primary,secondary,result) struct RexxMsg *RxMsg;
long primary,secondary;
char *result;
{

  if (!primary && (RxMsg->rm_Action & RXFF_RESULT) )
  {
    secondary = (result ? (LONG) CreateArgstring(result,strlen(result))
                        : NULL);
  }
  RxMsg->rm_Result1 = primary;
  RxMsg->rm_Result2 = secondary;
  ReplyMsg(RxMsg);
}

/*--------------------------------------------------------*/
/*        Hier beginnt der Assembler-Teil für das         */
/*                Aufrufen der RexxSysLib                 */
/*--------------------------------------------------------*/
#asm

* hier folgt ein Auszug aus den Definitionen in exec/libraries.i

LIB_VECTSIZE    EQU     6
LIB_RESERVED    EQU     4
LIB_BASE        EQU     $FFFFFFFA
LIB_USERDEF     EQU     LIB_BASE-(LIB_RESERVED*LIB_VECTSIZE)
LIB_NONSTD      EQU     LIB_USERDEF
LIBINIT     MACRO   *
     IFC     '\1',''
COUNT_LIB   SET     LIB_USERDEF
     ENDC
     IFNC    '\1',''
COUNT_LIB   SET     \1
     ENDC
     ENDM
LIBDEF      MACRO   *
\1          EQU     COUNT_LIB
COUNT_LIB   SET     COUNT_LIB-LIB_VECTSIZE
     ENDM

* Libraryoffsets der RexxLib

         LIBINIT
         LIBDEF   _LVORexx            
         LIBDEF   _LVOrxParse         
         LIBDEF   _LVOrxInstruct      
         LIBDEF   _LVOrxSuspend       
         LIBDEF   _LVOEvalOp          

         LIBDEF   _LVOAssignValue     
         LIBDEF   _LVOEnterSymbol     
         LIBDEF   _LVOFetchValue      
         LIBDEF   _LVOLookUpValue     
         LIBDEF   _LVOSetValue        
         LIBDEF   _LVOSymExpand       

         LIBDEF   _LVOErrorMsg
         LIBDEF   _LVOIsSymbol
         LIBDEF   _LVOCurrentEnv
         LIBDEF   _LVOGetSpace
         LIBDEF   _LVOFreeSpace

         LIBDEF   _LVOCreateArgstring
         LIBDEF   _LVODeleteArgstring
         LIBDEF   _LVOLengthArgstring
         LIBDEF   _LVOCreateRexxMsg
         LIBDEF   _LVODeleteRexxMsg
         LIBDEF   _LVOClearRexxMsg
         LIBDEF   _LVOFillRexxMsg
         LIBDEF   _LVOIsRexxMsg

         LIBDEF   _LVOAddRsrcNode
         LIBDEF   _LVOFindRsrcNode
         LIBDEF   _LVORemRsrcList
         LIBDEF   _LVORemRsrcNode
         LIBDEF   _LVOOpenPublicPort
         LIBDEF   _LVOClosePublicPort
         LIBDEF   _LVOListNames

         LIBDEF   _LVOClearMem
         LIBDEF   _LVOInitList
         LIBDEF   _LVOInitPort
         LIBDEF   _LVOFreePort

         LIBDEF   _LVOCmpString
         LIBDEF   _LVOStcToken
         LIBDEF   _LVOStrcmpN
         LIBDEF   _LVOStrcmpU
         LIBDEF   _LVOStrcpyA         
         LIBDEF   _LVOStrcpyN
         LIBDEF   _LVOStrcpyU
         LIBDEF   _LVOStrflipN
         LIBDEF   _LVOStrlen
         LIBDEF   _LVOToUpper

         LIBDEF   _LVOCVa2i
         LIBDEF   _LVOCVi2a
         LIBDEF   _LVOCVi2arg
         LIBDEF   _LVOCVi2az
         LIBDEF   _LVOCVc2x
         LIBDEF   _LVOCVx2c

         LIBDEF   _LVOOpenF
         LIBDEF   _LVOCloseF
         LIBDEF   _LVOReadStr
         LIBDEF   _LVOReadF
         LIBDEF   _LVOWriteF
         LIBDEF   _LVOSeekF
         LIBDEF   _LVOQueueF
         LIBDEF   _LVOStackF
         LIBDEF   _LVOExistF

         LIBDEF   _LVODOSCommand
         LIBDEF   _LVODOSRead
         LIBDEF   _LVODOSWrite
         LIBDEF   _LVOCreateDOSPkt    
         LIBDEF   _LVODeleteDOSPkt    
         LIBDEF   _LVOSendDOSPkt      
         LIBDEF   _LVOWaitDOSPkt      
         LIBDEF   _LVOFindDevice

         LIBDEF   _LVOAddClipNode
         LIBDEF   _LVORemClipNode
         LIBDEF   _LVOLockRexxBase
         LIBDEF   _LVOUnlockRexxBase
         LIBDEF   _LVOCreateCLI
         LIBDEF   _LVODeleteCLI
         LIBDEF   _LVOCVs2i

* Dieser Wert muß vorher mit OpenLibrary("rexxsyslib.library",0L)
* gesetzt werden:
         public     _RexxSysBase

* Es folgen die verwendeten Funktionsaufrufe:
         public     _CreateRexxMsg
         public     _DeleteRexxMsg
         public     _CreateArgstring
         public     _DeleteArgstring

* -------------------- Nun die Glue-Routinen: -------------------
_CreateRexxMsg:
         MOVE.W   #_LVOCreateRexxMsg,D1
         BRA.S    TwoArgs

_DeleteRexxMsg:
         MOVE.W   #_LVODeleteRexxMsg,D1
         BRA.S    TwoArgs

_CreateArgstring:
         MOVEQ    #_LVOCreateArgstring,D1
         BRA.S    OneArg

_DeleteArgstring:
         MOVE.W   #_LVODeleteArgstring,D1
         BRA.S    TwoArgs

OneArg:
         MOVEA.L  4(SP),A0
         MOVE.L   8(SP),D0
         BRA      RxJmp

TwoArgs:
         MOVEM.L  4(SP),A0/A1
         MOVE.L   12(SP),D0
RxJmp:
         MOVE.L   A6,-(SP)
         MOVEA.L  _RexxSysBase,A6
         JSR      0(A6,D1.W)
         MOVEA.L  (SP)+,A6
         RTS
#endasm
