From 6eb56b056e3d100f46a27ff34baaf2f55c6850b1 Mon Sep 17 00:00:00 2001 From: Carsten Larsen Date: Mon, 11 Jan 2021 20:33:26 +0100 Subject: [PATCH] ARexx support --- .vscode/c_cpp_properties.json | 19 ++++ builddist | 9 +- configure | 11 +- src/system/amiga_arexx.cpp | 208 ++++++++++++++++++++++++++++++++++ src/system/amiga_arexx.h | 75 ++++++++++++ src/system/program_amiga.cpp | 14 ++- 6 files changed, 325 insertions(+), 11 deletions(-) create mode 100644 .vscode/c_cpp_properties.json create mode 100644 src/system/amiga_arexx.cpp create mode 100644 src/system/amiga_arexx.h diff --git a/.vscode/c_cpp_properties.json b/.vscode/c_cpp_properties.json new file mode 100644 index 00000000..88708823 --- /dev/null +++ b/.vscode/c_cpp_properties.json @@ -0,0 +1,19 @@ +{ + "configurations": [ + { + "name": "amiga", + "includePath": [ + "/opt/amiga/m68k-amigaos/ndk-include/", + "/opt/amiga/m68k-amigaos/clib2/include/", + "${workspaceFolder}/src/lib/" + ], + "defines": ["AMIGA"], + "compilerPath": "/opt/amiga/bin/m68k-amigaos-gcc", + "cStandard": "c99", + "cppStandard": "c++98", + "intelliSenseMode": "${default}", + "compilerArgs": [] + } + ], + "version": 4 +} \ No newline at end of file diff --git a/builddist b/builddist index 5587b26f..b7d15442 100755 --- a/builddist +++ b/builddist @@ -1,10 +1,13 @@ #!/bin/sh -# +# # This file is public domain -# +# # Project homepage: # https://amath.innolan.net -# +# + +# Add compiler path before invoking. Fx: +# export PATH="/opt/m68k-amigaos/bin/:$PATH" set -e diff --git a/configure b/configure index a9d64091..aee0e259 100755 --- a/configure +++ b/configure @@ -1,8 +1,8 @@ #!/bin/sh -# +# # 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: @@ -11,7 +11,7 @@ # 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 AND CONTRIBUTORS ``AS IS'' AND # ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE # IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE @@ -23,7 +23,7 @@ # 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. -# +# set -e @@ -264,7 +264,7 @@ if $stdlibm; then mflags="-DLIBM " dlibm=true fi - + if $openlibm; then libm="-lopenlibm " mflags="-DLIBM " @@ -306,6 +306,7 @@ values.cpp viewer.cpp ' SYSSRCS=' +amiga_arexx.cpp console.cpp console_amiga.cpp console_stdc.cpp diff --git a/src/system/amiga_arexx.cpp b/src/system/amiga_arexx.cpp new file mode 100644 index 00000000..4ea29020 --- /dev/null +++ b/src/system/amiga_arexx.cpp @@ -0,0 +1,208 @@ +/*- + * 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 \ No newline at end of file diff --git a/src/system/amiga_arexx.h b/src/system/amiga_arexx.h new file mode 100644 index 00000000..5d489357 --- /dev/null +++ b/src/system/amiga_arexx.h @@ -0,0 +1,75 @@ +/*- + * 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 + * + */ + +#ifndef AMATH_AREXX +#define AMATH_AREXX + +/** + * @file console.h + * @brief Generic console system calls. + * + */ + +#if defined(AMIGA) + +#ifndef AREXXPORTNAME +#define AREXXPORTNAME "AMATH." +#endif + +#ifndef AREXXPROCNAME +#define AREXXPROCNAME "amath ARexx process" +#endif + +/** + * @brief Abstract base class encapsulating console logic. + * + */ +class AmigaARexx +{ +public: + AmigaARexx(); + ~AmigaARexx(); + bool Start(); + void Stop(); + +private: + static void ProcessEntry(); + void Process(); + void CreatePort(); + void PublishPort(); + void DestroyPort(); + bool HandleMessage(struct RexxMsg *message); + + char portName[10]; + struct Process *process; + struct MsgPort *port; +}; + +#endif +#endif diff --git a/src/system/program_amiga.cpp b/src/system/program_amiga.cpp index 9d803c66..3242129e 100644 --- a/src/system/program_amiga.cpp +++ b/src/system/program_amiga.cpp @@ -24,7 +24,7 @@ * * Project homepage: * https://amath.innolan.net - * + * */ #include "amath.h" @@ -39,6 +39,7 @@ #include "preferences_amiga.h" #include "lib/charbuf.h" #include "main/evaluator.h" +#include "amiga_arexx.h" #if defined(AMIGA) #define ARGS_FORMAT "SHELL/S,NOANSI/S,INPUT/F" @@ -83,7 +84,7 @@ void AmigaProgram::Initialize(int argc, char **argv) shellMode = args.shell ? true : false; ansiMode = args.noansi ? false : true; - + if (shellMode || args.input != nullptr) { Console = new AmigaShellConsole(Preferences->GetPrompt()); @@ -92,7 +93,7 @@ void AmigaProgram::Initialize(int argc, char **argv) { Console = new AmigaWindow(Preferences->GetPrompt(), Language); } - + InitAnsiMode(); } @@ -116,7 +117,14 @@ void AmigaProgram::Start() return; } + AmigaARexx *arexx = new AmigaARexx(); + arexx->Start(); + Console->Start(); + + arexx->Stop(); + delete arexx; + return; }