Use memory-allocation functions provided by the REXX interpreter.
[jog] / rxglue.c
index 75cd5c8..9126ff4 100644 (file)
--- a/rxglue.c
+++ b/rxglue.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: rxglue.c,v 1.1 2002/01/25 19:34:45 mdw Exp $
+ * $Id: rxglue.c,v 1.2 2002/01/30 09:22:48 mdw Exp $
  *
  * REXX glue for C core functionality
  *
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: rxglue.c,v $
+ * Revision 1.2  2002/01/30 09:22:48  mdw
+ * Use memory-allocation functions provided by the REXX interpreter.
+ * Now that configuration can be applied after initialization, allow
+ * @txconf@ to set parameters.  Make @txsend@ add a newline to its output,
+ * unless forbidden.
+ *
  * Revision 1.1  2002/01/25 19:34:45  mdw
  * Initial revision
  *
@@ -58,6 +64,7 @@
 #include <rexxsaa.h>
 
 #include <mLib/alloc.h>
+#include <mLib/exc.h>
 #include <mLib/dstr.h>
 
 #include "err.h"
 
 static txport *tx = 0;
 
+/*----- Memory allocation functions ---------------------------------------*/
+
+static void *rx_alloc(size_t sz)
+{
+  void *p = RexxAllocateMemory(sz);
+  if (!p)
+    THROW(EXC_NOMEM);
+  return (p);
+}
+
+static void rx_free(void *p)
+{
+  RexxFreeMemory(p);
+}
+
 /*----- Conversion functions ----------------------------------------------*/
 
 /* --- @rxs_putm@ --- *
@@ -93,7 +115,7 @@ static txport *tx = 0;
   const void *_p = (p);                                                        \
   size_t _sz = (sz);                                                   \
   if (!_x->strptr || _x->strlength < _sz)                              \
-    _x->strptr = xmalloc(_sz);                                         \
+    _x->strptr = rx_alloc(_sz);                                                \
   memcpy(_x->strptr, _p, _sz);                                         \
   _x->strlength = _sz;                                                 \
 } while (0)
@@ -241,8 +263,8 @@ static int rxs_block(const RXSTRING *x, unsigned long *t)
 
 /*----- REXX functions ----------------------------------------------------*/
 
-static APIRET APIENTRY rxfn_test(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_test(const char *fn, ULONG ac, RXSTRING *av,
+                                const char *sn, RXSTRING *r)
 {
   ULONG i;
 
@@ -258,7 +280,7 @@ static APIRET APIENTRY rxfn_test(unsigned char *fn, ULONG ac, RXSTRING *av,
     else
       printf("' (%ld)\n", l);
   }
-  printf("tx = `%s'; f = `%s'; c = `%s'.", txname, txfile, txconf);
+  printf("tx = `%s'; f = `%s'; c = `%s'.\n", txname, txfile, txconf);
   rxs_putf(r, "function `%s' completed ok", fn);
   return (0);
 }
@@ -270,8 +292,8 @@ static APIRET APIENTRY rxfn_test(unsigned char *fn, ULONG ac, RXSTRING *av,
  * Returns:    The currently-selected transport name.
  */
 
-static APIRET APIENTRY rxfn_txname(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txname(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
   if (ac)
     return (-1);
@@ -286,8 +308,8 @@ static APIRET APIENTRY rxfn_txname(unsigned char *fn, ULONG ac, RXSTRING *av,
  * Returns:    The currently-selected transport filename.
  */
 
-static APIRET APIENTRY rxfn_txfile(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txfile(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
   if (ac)
     return (-1);
@@ -295,18 +317,29 @@ static APIRET APIENTRY rxfn_txfile(unsigned char *fn, ULONG ac, RXSTRING *av,
   return (0);
 }
 
-/* --- @txfile()@ ---
+/* --- @txconf([CONFIG])@ ---
  *
- * Arguments:  ---
+ * Arguments:  @CONFIG@ = optional string to set
  *
  * Returns:    The currently-selected transport configuration string.
  */
 
-static APIRET APIENTRY rxfn_txconf(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txconf(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
-  if (ac)
+  if (ac > 1)
     return (-1);
+  if (ac > 0 && av[0].strptr) {
+    dstr d = DSTR_INIT;
+    int rc;
+    if (!tx)
+      return (-1);
+    rxs_get(&av[0], &d);
+    rc = tx_configure(tx, d.buf);
+    dstr_destroy(&d);
+    if (rc)
+      return (-1);
+  }
   rxs_putf(r, "%s", txconf ? txconf : "");
   return (0);
 }
@@ -324,8 +357,8 @@ static APIRET APIENTRY rxfn_txconf(unsigned char *fn, ULONG ac, RXSTRING *av,
  *             defaults.
  */
 
-static APIRET APIENTRY rxfn_txinit(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txinit(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
   const char *n = txname, *f = txfile, *c = txconf;
   dstr dn = DSTR_INIT, df = DSTR_INIT, dc = DSTR_INIT;
@@ -343,7 +376,7 @@ static APIRET APIENTRY rxfn_txinit(unsigned char *fn, ULONG ac, RXSTRING *av,
     f = df.buf;
   }
   if (ac >= 3 && av[2].strptr) {
-    rxs_get(&av[2], &dn);
+    rxs_get(&av[2], &dc);
     c = dc.buf;
   }
   tx = tx_create(n, f, c);
@@ -355,21 +388,25 @@ static APIRET APIENTRY rxfn_txinit(unsigned char *fn, ULONG ac, RXSTRING *av,
   return (0);
 }
 
-/* --- @txsend(STRING)@ --- *
+/* --- @txsend(STRING, [OPTION])@ --- *
  *
  * Arguments:  @STRING@ = string to send
+ *             @OPTION@ = `l' or `n' (for `linebreak' or `nolinebreak')
  *
  * Returns:    ---
  *
  * Use:                Sends a string (exactly as written) to the transport.
  */
 
-static APIRET APIENTRY rxfn_txsend(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txsend(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
-  if (ac != 1 || !tx || !av[0].strptr)
+  if ((ac != 1 && ac != 2) || !tx || !av[0].strptr)
     return (-1);
   tx_write(tx, av[0].strptr, av[0].strlength);
+  if (ac == 1 || !av[1].strptr || !av[1].strlength ||
+      av[1].strptr[0] == 'l' || av[1].strptr[0] == 'L')
+    tx_newline(tx);
   return (0);
 }
 
@@ -385,8 +422,8 @@ static APIRET APIENTRY rxfn_txsend(unsigned char *fn, ULONG ac, RXSTRING *av,
  *             `f') then don't give up.  The default is to wait forever.
  */
 
-static APIRET APIENTRY rxfn_txrecv(unsigned char *fn, ULONG ac, RXSTRING *av,
-                                  char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txrecv(const char *fn, ULONG ac, RXSTRING *av,
+                                  const char *sn, RXSTRING *r)
 {
   txline *l;
   unsigned long t = FOREVER;
@@ -414,8 +451,8 @@ static APIRET APIENTRY rxfn_txrecv(unsigned char *fn, ULONG ac, RXSTRING *av,
  *             false.
  */
 
-static APIRET APIENTRY rxfn_txeof(unsigned char *fn, ULONG ac,
-                                 RXSTRING *av, char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txeof(const char *fn, ULONG ac, RXSTRING *av,
+                                 const char *sn, RXSTRING *r)
 {
   if (ac || !tx)
     return (-1);
@@ -438,8 +475,8 @@ static APIRET APIENTRY rxfn_txeof(unsigned char *fn, ULONG ac,
  *             0 had been specified).
  */
 
-static APIRET APIENTRY rxfn_txready(unsigned char *fn, ULONG ac,
-                                   RXSTRING *av, char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_txready(const char *fn, ULONG ac, RXSTRING *av,
+                                   const char *sn, RXSTRING *r)
 {
   unsigned long t = 0;
 
@@ -460,8 +497,8 @@ static APIRET APIENTRY rxfn_txready(unsigned char *fn, ULONG ac,
  * Use:                Waits for @MILLIS@ milliseconds.  Always.
  */
 
-static APIRET APIENTRY rxfn_milliwait(unsigned char *fn, ULONG ac,
-                                     RXSTRING *av, char *sn, RXSTRING *r)
+static APIRET APIENTRY rxfn_milliwait(const char *fn, ULONG ac, RXSTRING *av,
+                                     const char *sn, RXSTRING *r)
 {
   long l;
   struct timeval tv;
@@ -481,16 +518,16 @@ static APIRET APIENTRY rxfn_milliwait(unsigned char *fn, ULONG ac,
 struct rxfntab { char *name; RexxFunctionHandler *fn; };
 
 static const struct rxfntab rxfntab[] = {
-  { "test",    rxfn_test },
-  { "txname",  rxfn_txname },
-  { "txfile",  rxfn_txfile },
-  { "txconf",  rxfn_txconf },
-  { "txinit",  rxfn_txinit },
-  { "txsend",  rxfn_txsend },
-  { "txrecv",  rxfn_txrecv },
-  { "txeof",   rxfn_txeof },
-  { "txready", rxfn_txready },
-  { "milliwait", rxfn_milliwait },
+  { "test",            rxfn_test },
+  { "txname",          rxfn_txname },
+  { "txfile",          rxfn_txfile },
+  { "txconf",          rxfn_txconf },
+  { "txinit",          rxfn_txinit },
+  { "txsend",          rxfn_txsend },
+  { "txrecv",          rxfn_txrecv },
+  { "txeof",           rxfn_txeof },
+  { "txready",         rxfn_txready },
+  { "milliwait",       rxfn_milliwait },
   { 0,         0 }
 };
 
@@ -549,17 +586,18 @@ int rx_run(const char *name, const void *p, size_t sz,
     name = "incore";
   MAKERXSTRING(prog[0], (void *)p, sz);
   MAKERXSTRING(prog[1], 0, 0);
-  argv = xmalloc(ac * sizeof(*argv));
+  argv = rx_alloc(ac * sizeof(*argv));
   for (i = 0; i < ac; i++)
     MAKERXSTRING(argv[i], (char *)av[i], strlen(av[i]));
 
   /* --- Run the script --- */
 
   MAKERXSTRING(res, 0, 0);
-  rc = RexxStart(ac, argv, (char *)name, prog,
-                "CMD", RXCOMMAND, 0, &badrc, &res);
+  rc = RexxStart(ac, argv, name, prog,
+                "SYSTEM", RXSUBROUTINE, 0, &badrc, &res);
   if (rc) {
-    free(RXSTRPTR(res));
+    rx_free(RXSTRPTR(res));
+    rx_free(argv);
     if (rc < 0)
       err_report(ERR_RXERR, 0, -rc, "rexx error from script `%s'", name);
     else
@@ -570,7 +608,8 @@ int rx_run(const char *name, const void *p, size_t sz,
   /* --- Pick apart the results --- */
 
   dstr_putm(&d, RXSTRPTR(res), RXSTRLEN(res));
-  free(RXSTRPTR(res));
+  rx_free(RXSTRPTR(res));
+  rx_free(argv);
   dstr_putz(&d);
   rc = atoi(d.buf);
   dstr_destroy(&d);