/* -*-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
*
#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@ --- *
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)
/*----- 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;
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);
}
* 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);
* 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);
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);
}
* 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;
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);
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);
}
* `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;
* 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);
* 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;
* 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;
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 }
};
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
/* --- 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);