/*- * Copyright (c) 2014-2018 Carsten Sonne Larsen * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. * * Project homepage: * https://amath.innolan.net * */ #include "amathc.h" #include "amiga_arexx.h" #include "lib/charbuf.h" #include "main/evaluator.h" #if defined(AMIGA) #include #include #include #include #include #include #ifndef RXSNAME #define RXSNAME "rexxsyslib.library" #endif struct RxsLib *RexxSysBase = NULL; AmigaARexx::AmigaARexx() { RexxSysBase = (struct RxsLib *)OpenLibrary((STRPTR)RXSNAME, 0); } AmigaARexx::~AmigaARexx() { if (RexxSysBase != NULL) { CloseLibrary((struct Library *)RexxSysBase); } } void AmigaARexx::CreatePort() { port = CreateMsgPort(); if (port != NULL) { PublishPort(); } } void AmigaARexx::DestroyPort() { if (port != NULL) { RemPort(port); struct Message *msg; while ((msg = GetMsg(port))) { ReplyMsg(msg); } DeleteMsgPort(port); } } void AmigaARexx::PublishPort() { CharBuffer *buf = new CharBuffer(12); bool published = false; int c = 0; do { c++; buf->ClearAndCopy(AREXXPORTNAME); buf->AppendNumber(c); buf->CopyTo(portName); Forbid(); struct MsgPort *msgPort = FindPort((CONST_STRPTR)portName); if (msgPort == NULL) { port->mp_Node.ln_Pri = 0; port->mp_Node.ln_Name = portName; AddPort((struct MsgPort *)port); published = true; } Permit(); } while (!published); delete buf; } static AmigaARexx *newProcess; void AmigaARexx::ProcessEntry() { newProcess->Process(); } bool AmigaARexx::Start() { Forbid(); newProcess = this; process = CreateNewProcTags( NP_Entry, (void *)ProcessEntry, NP_Name, (APTR)AREXXPROCNAME, NP_StackSize, 64 * 1024, TAG_DONE); Permit(); return (process != NULL); } void AmigaARexx::Stop() { if (port == NULL) { return; } struct MsgPort *replyPort = CreateMsgPort(); if (replyPort != NULL) { struct RexxMsg *message = (struct RexxMsg *)AllocVec(sizeof(struct RexxMsg), MEMF_ANY | MEMF_CLEAR); if (message != NULL) { message->rm_Node.mn_Node.ln_Type = NT_MESSAGE; message->rm_Node.mn_Length = sizeof(struct RexxMsg); message->rm_Node.mn_ReplyPort = replyPort; message->rm_Result1 = 99; Forbid(); PutMsg(port, (struct Message *)message); Permit(); WaitPort(replyPort); GetMsg(replyPort); FreeVec(message); } DeleteMsgPort(replyPort); } } void AmigaARexx::Process() { CreatePort(); if (port != NULL) { bool loop = true; do { WaitPort(port); struct RexxMsg *msg; while ((msg = (struct RexxMsg *)GetMsg(port))) { loop &= HandleMessage(msg); ReplyMsg((struct Message *)msg); } } while (loop); } DestroyPort(); } bool AmigaARexx::HandleMessage(struct RexxMsg *message) { if (message->rm_Result1 == 99) { return false; } message->rm_Result1 = 0; if (message->rm_Action & RXFF_RESULT) { Evaluator *evaluator = new Evaluator(message->rm_Args[0]); evaluator->Evaluate(); const char *result = evaluator->GetResult(); message->rm_Result2 = (LONG)CreateArgstring((STRPTR)result, (LONG)StrLen(result)); delete evaluator; } return true; } #endif