aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--jim-aio.c758
-rw-r--r--jim-eventloop.c12
-rw-r--r--jim-file.c3
-rw-r--r--jim-subcmd.c7
-rw-r--r--jim-subcmd.h3
-rw-r--r--jim.c4
-rwxr-xr-xtcltests/runtests21
-rw-r--r--tcltests/test_bio.tcl4
-rw-r--r--tcltests/test_read.tcl5
9 files changed, 459 insertions, 358 deletions
diff --git a/jim-aio.c b/jim-aio.c
index f8f118a..d47f799 100644
--- a/jim-aio.c
+++ b/jim-aio.c
@@ -52,6 +52,7 @@
#include "jim.h"
#include "jim-eventloop.h"
+#include "jim-subcmd.h"
#define AIO_CMD_LEN 128
@@ -74,7 +75,7 @@ typedef struct AioFile {
struct hostent *he;
} AioFile;
-static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af );
+static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
static void JimAioFileEventFinalizer(Jim_Interp *interp, void *clientData)
{
@@ -87,9 +88,10 @@ static int JimAioFileEventHandler(Jim_Interp *interp, void *clientData, int mask
{
Jim_Obj *objPtr = clientData;
Jim_Obj *scrPtr = NULL ;
- if ( mask == (JIM_EVENT_READABLE | JIM_EVENT_FEOF)) {
+ if (mask == (JIM_EVENT_READABLE | JIM_EVENT_FEOF)) {
Jim_ListIndex(interp, objPtr, 1, &scrPtr, 0);
- } else {
+ }
+ else {
Jim_ListIndex(interp, objPtr, 0, &scrPtr, 0);
}
Jim_EvalObjBackground(interp, scrPtr);
@@ -106,360 +108,459 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
AioFile *af = privData;
JIM_NOTUSED(interp);
- if (!(af->OpenFlags & AIO_KEEPOPEN))
+ if (!(af->OpenFlags & AIO_KEEPOPEN)) {
fclose(af->fp);
- if (!af->OpenFlags == AIO_FDOPEN) // fp = fdopen(fd) !!
+ }
+ if (!af->OpenFlags == AIO_FDOPEN) {
close(af->fd);
+ }
#ifdef with_jim_ext_eventloop
- if (af->rEvent) { // remove existing EventHandlers
+ /* remove existing EventHandlers */
+ if (af->rEvent) {
Jim_DeleteFileHandler(interp,af->fp);
- Jim_DecrRefCount(interp,af->rEvent);
}
if (af->wEvent) {
Jim_DeleteFileHandler(interp,af->fp);
- Jim_DecrRefCount(interp,af->wEvent);
}
if (af->eEvent) {
Jim_DeleteFileHandler(interp,af->fp);
- Jim_DecrRefCount(interp,af->eEvent);
}
#endif
Jim_Free(af);
}
-/* Calls to [aio.file] create commands that are implemented by this
- * C command. */
-static int JimAioHandlerCommand(Jim_Interp *interp, int argc,
- Jim_Obj *const *argv)
+static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
- int option;
- const char *options[] = {
- "close",
- "seek", "tell",
- "gets", "read", "puts",
- "flush", "eof",
- "ndelay",
-#ifdef with_jim_ext_eventloop
- "readable", "writable", "onexception",
-#endif
- "accept",
- NULL
- };
- enum {OPT_CLOSE,
- OPT_SEEK, OPT_TELL,
- OPT_GETS, OPT_READ, OPT_PUTS,
- OPT_FLUSH, OPT_EOF,
- OPT_NDELAY,
-#ifdef with_jim_ext_eventloop
- OPT_READABLE, OPT_WRITABLE, OPT_EXCEPTION,
-#endif
- OPT_ACCEPT,
- };
-
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "method ?args ...?");
- return JIM_ERR;
+ char buf[AIO_BUF_LEN];
+ Jim_Obj *objPtr;
+ int nonewline = 0;
+ int neededLen = -1; /* -1 is "read as much as possible" */
+
+ if (argc && Jim_CompareStringImmediate(interp, argv[0], "-nonewline"))
+ {
+ nonewline = 1;
+ argv++;
+ argc--;
}
- if (Jim_GetEnum(interp, argv[1], options, &option, "AIO method",
- JIM_ERRMSG) != JIM_OK)
- return JIM_ERR;
- /* CLOSE */
- if (option == OPT_CLOSE) {
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
+ if (argc == 1) {
+ jim_wide wideValue;
+ if (Jim_GetWide(interp, argv[0], &wideValue) != JIM_OK)
return JIM_ERR;
- }
- Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL));
- return JIM_OK;
- } else if (option == OPT_SEEK) {
- /* SEEK */
- int orig = SEEK_SET;
- long offset;
-
- if (argc != 3 && argc != 4) {
- Jim_WrongNumArgs(interp, 2, argv, "offset ?origin?");
+ if (wideValue < 0) {
+ Jim_SetResultString(interp, "invalid parameter: negative len",
+ -1);
return JIM_ERR;
}
- if (argc == 4) {
- if (Jim_CompareStringImmediate(interp, argv[3], "start"))
- orig = SEEK_SET;
- else if (Jim_CompareStringImmediate(interp, argv[3], "current"))
- orig = SEEK_CUR;
- else if (Jim_CompareStringImmediate(interp, argv[3], "end"))
- orig = SEEK_END;
- else {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- Jim_AppendStrings(interp, Jim_GetResult(interp),
- "bad origin \"", Jim_GetString(argv[3], NULL),
- "\" must be: start, current, or end", NULL);
- return JIM_ERR;
- }
+ neededLen = (int) wideValue;
+ }
+ else if (argc) {
+ return -1;
+ }
+ objPtr = Jim_NewStringObj(interp, NULL, 0);
+ while (neededLen != 0) {
+ int retval;
+ int readlen;
+
+ if (neededLen == -1) {
+ readlen = AIO_BUF_LEN;
+ } else {
+ readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
}
- if (Jim_GetLong(interp, argv[2], &offset) != JIM_OK)
- return JIM_ERR;
- if (fseek(af->fp, offset, orig) == -1) {
- JimAioSetError(interp);
- return JIM_ERR;
+ retval = fread(buf, 1, readlen, af->fp);
+ if (retval > 0) {
+ Jim_AppendString(interp, objPtr, buf, retval);
+ if (neededLen != -1) {
+ neededLen -= retval;
+ }
}
- return JIM_OK;
- } else if (option == OPT_TELL) {
- /* TELL */
- long position;
+ if (retval != readlen) break;
+ }
+ /* Check for error conditions */
+ if (ferror(af->fp)) {
+ /* I/O error */
+ Jim_FreeNewObj(interp, objPtr);
+ JimAioSetError(interp);
+ return JIM_ERR;
+ }
+ if (nonewline) {
+ int len;
+ const char *s = Jim_GetString(objPtr, &len);
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
- return JIM_ERR;
+ if (len > 0 && s[len-1] == '\n') {
+ objPtr->length--;
+ objPtr->bytes[objPtr->length] = '\0';
}
- position = ftell(af->fp);
- Jim_SetResult(interp, Jim_NewIntObj(interp, position));
- return JIM_OK;
- } else if (option == OPT_GETS) {
- /* GETS */
- char buf[AIO_BUF_LEN];
- Jim_Obj *objPtr;
+ }
+ Jim_SetResult(interp, objPtr);
+ return JIM_OK;
+}
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "?varName?");
- return JIM_ERR;
- }
- objPtr = Jim_NewStringObj(interp, NULL, 0);
- while (1) {
- int more = 0;
- buf[AIO_BUF_LEN-1] = '_';
- if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
- break;
- if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN-2] != '\n')
- more = 1;
- if (more) {
- Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1);
- } else {
- /* strip "\n" */
- Jim_AppendString(interp, objPtr, buf, strlen(buf)-1);
- }
- if (!more)
- break;
- }
- if (ferror(af->fp) && (errno != EAGAIN)) {
- /* I/O error */
- Jim_IncrRefCount(objPtr);
- Jim_DecrRefCount(interp, objPtr);
- JimAioSetError(interp);
- return JIM_ERR;
- }
- /* On EOF returns -1 if varName was specified, or the empty string. */
- if (feof(af->fp) && Jim_Length(objPtr) == 0) {
- Jim_IncrRefCount(objPtr);
- Jim_DecrRefCount(interp, objPtr);
- if (argc == 3)
- Jim_SetResult(interp, Jim_NewIntObj(interp, -1));
- return JIM_OK;
- }
- if (argc == 3) {
- int totLen;
-
- Jim_GetString(objPtr, &totLen);
- if (Jim_SetVariable(interp, argv[2], objPtr) != JIM_OK) {
- Jim_IncrRefCount(objPtr);
- Jim_DecrRefCount(interp, objPtr);
- return JIM_ERR;
- }
- Jim_SetResult(interp, Jim_NewIntObj(interp, totLen));
+static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ char buf[AIO_BUF_LEN];
+ Jim_Obj *objPtr;
+
+ objPtr = Jim_NewStringObj(interp, NULL, 0);
+ while (1) {
+ int more = 0;
+ buf[AIO_BUF_LEN-1] = '_';
+ if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
+ break;
+ if (buf[AIO_BUF_LEN-1] == '\0' && buf[AIO_BUF_LEN-2] != '\n')
+ more = 1;
+ if (more) {
+ Jim_AppendString(interp, objPtr, buf, AIO_BUF_LEN-1);
} else {
- Jim_SetResult(interp, objPtr);
- }
- return JIM_OK;
- } else if (option == OPT_READ) {
- /* READ */
- char buf[AIO_BUF_LEN];
- Jim_Obj *objPtr;
- int nonewline = 0;
- int neededLen = -1; /* -1 is "read as much as possible" */
-
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? ?len?");
- return JIM_ERR;
- }
- if (argc == 3 &&
- Jim_CompareStringImmediate(interp, argv[2], "-nonewline"))
- {
- nonewline = 1;
- argv++;
- argc--;
- }
- if (argc == 3) {
- jim_wide wideValue;
- if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK)
- return JIM_ERR;
- if (wideValue < 0) {
- Jim_SetResultString(interp, "invalid parameter: negative len",
- -1);
- return JIM_ERR;
- }
- neededLen = (int) wideValue;
+ /* strip "\n" */
+ Jim_AppendString(interp, objPtr, buf, strlen(buf)-1);
}
- objPtr = Jim_NewStringObj(interp, NULL, 0);
- while (neededLen != 0) {
- int retval;
- int readlen;
-
- if (neededLen == -1) {
- readlen = AIO_BUF_LEN;
- } else {
- readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
- }
- retval = fread(buf, 1, readlen, af->fp);
- if (retval > 0) {
- Jim_AppendString(interp, objPtr, buf, retval);
- if (neededLen != -1) {
- neededLen -= retval;
- }
- }
- if (retval != readlen) break;
+ if (!more)
+ break;
+ }
+ if (ferror(af->fp) && (errno != EAGAIN)) {
+ /* I/O error */
+ Jim_FreeNewObj(interp, objPtr);
+ JimAioSetError(interp);
+ return JIM_ERR;
+ }
+ /* On EOF returns -1 if varName was specified, or the empty string. */
+ if (feof(af->fp) && Jim_Length(objPtr) == 0) {
+ Jim_FreeNewObj(interp, objPtr);
+ if (argc) {
+ Jim_SetResultInt(interp, -1);
}
- /* Check for error conditions */
- if (ferror(af->fp)) {
- /* I/O error */
+ return JIM_OK;
+ }
+ if (argc) {
+ int totLen;
+
+ Jim_GetString(objPtr, &totLen);
+ if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) {
Jim_FreeNewObj(interp, objPtr);
- JimAioSetError(interp);
return JIM_ERR;
}
- if (nonewline) {
- int len;
- const char *s = Jim_GetString(objPtr, &len);
+ Jim_SetResultInt(interp, totLen);
+ }
+ else {
+ Jim_SetResult(interp, objPtr);
+ }
+ return JIM_OK;
+}
- if (len > 0 && s[len-1] == '\n') {
- objPtr->length--;
- objPtr->bytes[objPtr->length] = '\0';
- }
+static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ int wlen;
+ const char *wdata;
+ Jim_Obj *strObj;
+
+ if (argc == 2) {
+ if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
+ return -1;
}
- Jim_SetResult(interp, objPtr);
- return JIM_OK;
- } else if (option == OPT_PUTS) {
- /* PUTS */
- int wlen;
- const char *wdata;
-
- if (argc != 3 && (argc != 4 || !Jim_CompareStringImmediate(
- interp, argv[2], "-nonewline"))) {
- Jim_WrongNumArgs(interp, 2, argv, "?-nonewline? string");
- return JIM_ERR;
+ strObj = argv[1];
+ }
+ else {
+ strObj = argv[0];
+ }
+
+ wdata = Jim_GetString(strObj, &wlen);
+ if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) {
+ if (argc == 2 || putc('\n', af->fp) != EOF) {
+ return JIM_OK;
}
- wdata = Jim_GetString(argv[2+(argc==4)], &wlen);
- if (fwrite(wdata, 1, wlen, af->fp) != (unsigned)wlen ||
- (argc == 3 && fwrite("\n", 1, 1, af->fp) != 1)) {
- JimAioSetError(interp);
- return JIM_ERR;
+ }
+ JimAioSetError(interp);
+ return JIM_ERR;
+}
+
+static int aio_cmd_flush(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ if (fflush(af->fp) == EOF) {
+ JimAioSetError(interp);
+ return JIM_ERR;
+ }
+ return JIM_OK;
+}
+
+static int aio_cmd_eof(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ Jim_SetResultInt(interp, feof(af->fp));
+ return JIM_OK;
+}
+
+static int aio_cmd_close(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ Jim_DeleteCommand(interp, Jim_GetString(argv[0], NULL));
+ return JIM_OK;
+}
+
+static int aio_cmd_seek(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ int orig = SEEK_SET;
+ long offset;
+
+ if (argc == 2) {
+ if (Jim_CompareStringImmediate(interp, argv[1], "start"))
+ orig = SEEK_SET;
+ else if (Jim_CompareStringImmediate(interp, argv[1], "current"))
+ orig = SEEK_CUR;
+ else if (Jim_CompareStringImmediate(interp, argv[1], "end"))
+ orig = SEEK_END;
+ else {
+ return -1;
}
- return JIM_OK;
- } else if (option == OPT_FLUSH) {
- /* FLUSH */
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
+ }
+ if (Jim_GetLong(interp, argv[0], &offset) != JIM_OK) {
+ return JIM_ERR;
+ }
+ if (fseek(af->fp, offset, orig) == -1) {
+ JimAioSetError(interp);
+ return JIM_ERR;
+ }
+ return JIM_OK;
+}
+
+static int aio_cmd_tell(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ Jim_SetResultInt(interp, ftell(af->fp));
+ return JIM_OK;
+}
+
+#ifdef O_NDELAY
+static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ int fmode = af->flags;
+
+ if (argc) {
+ long nb;
+
+ if (Jim_GetLong(interp, argv[2], &nb) != JIM_OK) {
return JIM_ERR;
}
- if (fflush(af->fp) == EOF) {
- JimAioSetError(interp);
- return JIM_ERR;
+ if (nb) {
+ fmode |= O_NDELAY;
}
- return JIM_OK;
- } else if (option == OPT_EOF) {
- /* EOF */
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 2, argv, "");
- return JIM_ERR;
+ else {
+ fmode &= ~O_NDELAY;
}
- Jim_SetResult(interp, Jim_NewIntObj(interp, feof(af->fp)));
- return JIM_OK;
- } else if (option == OPT_NDELAY) {
-#ifdef O_NDELAY
- int fmode = af->flags;
+ fcntl(af->fd, F_SETFL, fmode);
+ af->flags = fmode;
+ }
+ Jim_SetResultInt(interp, (fmode & O_NONBLOCK) ? 1 : 0);
+ return JIM_OK;
+}
+#endif
- if (argc == 3) {
- jim_wide wideValue;
+static int aio_cmd_accept(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *serv_af = Jim_CmdPrivData(interp);
+ int sock;
+ socklen_t addrlen = sizeof(struct sockaddr_in);
+ AioFile *af;
+ char buf[AIO_CMD_LEN];
+ long fileId;
+ sock = accept(serv_af->fd,(struct sockaddr*)&serv_af->sa,&addrlen);
+ if (sock < 0)
+ return JIM_ERR;
+
+ /* Get the next file id */
+ fileId = Jim_GetId(interp);
- if (Jim_GetWide(interp, argv[2], &wideValue) != JIM_OK)
- return JIM_ERR;
- switch (wideValue) {
- case 0:
- fmode &= ~O_NDELAY; break ;
- case 1:
- fmode |= O_NDELAY; break ;
+ /* Create the file command */
+ af = Jim_Alloc(sizeof(*af));
+ af->fd = sock;
+ af->fp = fdopen(sock,"r+");
+ af->OpenFlags = AIO_FDOPEN;
+ af->flags = fcntl(af->fd,F_GETFL);
+ af->rEvent = NULL;
+ af->wEvent = NULL;
+ af->eEvent = NULL;
+ sprintf(buf, "aio.sockstream%ld", fileId);
+ Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
+ Jim_SetResultString(interp, buf, -1);
+ return JIM_OK;
+}
+
+static int aio_eventinfo(Jim_Interp *interp, AioFile *af, unsigned mask, Jim_Obj **scriptListObj, Jim_Obj *script1, Jim_Obj *script2)
+{
+ int scriptlen = 0;
+
+ if (script1 == NULL) {
+ /* Return current script */
+ if (*scriptListObj) {
+ Jim_SetResult(interp, *scriptListObj);
}
- fcntl(af->fd,F_SETFL,fmode);
- af->flags = fmode;
- }
- Jim_SetResult(interp, Jim_NewIntObj(interp, (fmode & O_NONBLOCK)?1:0));
return JIM_OK;
-#else
- return JIM_ERR;
-#endif
}
-#ifdef with_jim_ext_eventloop
- else if ( (option == OPT_READABLE)
- || (option == OPT_WRITABLE)
- || (option == OPT_EXCEPTION)
- ) {
- int mask = 0;
- Jim_Obj **scrListObjpp = NULL;
- Jim_Obj *listObj;
- const char *dummy = NULL;
- int scrlen = 0;
-
- switch (option) {
- case OPT_READABLE: mask = JIM_EVENT_READABLE; scrListObjpp = &af->rEvent;
- if (argc == 4) mask |= JIM_EVENT_FEOF ; break;
- case OPT_WRITABLE: mask = JIM_EVENT_WRITABLE; scrListObjpp = &af->wEvent; break;
- case OPT_EXCEPTION: mask = JIM_EVENT_EXCEPTION; scrListObjpp = &af->eEvent; break;
- }
- switch (argc) {
- case 4:
- case 3:
- if (*scrListObjpp) {
- Jim_DeleteFileHandler(interp, af->fp); //,mask);
- Jim_DecrRefCount(interp, *scrListObjpp);
- *scrListObjpp = NULL;
- }
- if ( dummy = Jim_GetString(argv[2],&scrlen),(scrlen == 0)) {
- break;
- } else {
- *scrListObjpp = Jim_NewListObj(interp, NULL, 0);
- Jim_IncrRefCount(*scrListObjpp);
- listObj = argv[2];
- if (Jim_IsShared(listObj))
- listObj = Jim_DuplicateObj(interp, listObj);
- // Jim_IncrRefCount(listObj);
- Jim_ListAppendElement(interp,*scrListObjpp,listObj);
- if (mask & JIM_EVENT_FEOF) {
- listObj = argv[3];
- if (Jim_IsShared(listObj))
- listObj = Jim_DuplicateObj(interp, listObj);
- // Jim_IncrRefCount(listObj);
- Jim_ListAppendElement(interp,*scrListObjpp,listObj);
- }
- Jim_IncrRefCount(*scrListObjpp);
- Jim_CreateFileHandler(interp, af->fp, mask,
- JimAioFileEventHandler,
- *scrListObjpp,
- JimAioFileEventFinalizer);
- }
- break;
- case 2:
- if (*scrListObjpp)
- Jim_SetResult(interp,*scrListObjpp);
+
+ if (*scriptListObj) {
+ /* Delete old handler */
+ Jim_DeleteFileHandler(interp, af->fp);
+ *scriptListObj = NULL;
+ }
+
+ /* Now possibly add the new script(s) */
+ Jim_GetString(script1, &scriptlen);
+ if (scriptlen == 0) {
+ /* Empty script, so done */
return JIM_OK;
- default:
- Jim_WrongNumArgs(interp, 2, argv, "");
- return JIM_ERR;
- }
}
-#endif
- else if (option == OPT_ACCEPT) {
- return JimAioAcceptHelper(interp,af);
+
+ /* A new script to add */
+ *scriptListObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_IncrRefCount(*scriptListObj);
+
+ if (Jim_IsShared(script1)) {
+ script1 = Jim_DuplicateObj(interp, script1);
}
+ Jim_ListAppendElement(interp, *scriptListObj, script1);
+
+ if (script2) {
+ if (Jim_IsShared(script2)) {
+ script2 = Jim_DuplicateObj(interp, script2);
+ }
+ Jim_ListAppendElement(interp, *scriptListObj, script2);
+ }
+
+ Jim_CreateFileHandler(interp, af->fp, mask,
+ JimAioFileEventHandler,
+ *scriptListObj,
+ JimAioFileEventFinalizer);
+
return JIM_OK;
}
+#ifdef with_jim_ext_eventloop
+static int aio_cmd_readable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ Jim_Obj *eofScript = NULL;
+ int mask = JIM_EVENT_READABLE;
+
+
+ if (argc == 2) {
+ mask |= JIM_EVENT_FEOF;
+ eofScript = argv[1];
+ }
+
+ return aio_eventinfo(interp, af, mask, &af->rEvent, argc ? argv[0] : NULL, eofScript);
+}
+
+static int aio_cmd_writable(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ int mask = JIM_EVENT_WRITABLE;
+
+ return aio_eventinfo(interp, af, mask, &af->wEvent, argc ? argv[0] : NULL, NULL);
+}
+
+static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ int mask = JIM_EVENT_EXCEPTION;
+
+ return aio_eventinfo(interp, af, mask, &af->eEvent, argc ? argv[0] : NULL, NULL);
+}
+#endif
+
+static const jim_subcmd_type command_table[] = {
+ { .cmd = "read",
+ .args = "?-nonewline? ?len?",
+ .function = aio_cmd_read,
+ .minargs = 0,
+ .maxargs = 2,
+ .description = "Read and return bytes from the stream. To eof if no len."
+ },
+ { .cmd = "gets",
+ .args = "?var?",
+ .function = aio_cmd_gets,
+ .minargs = 0,
+ .maxargs = 1,
+ .description = "Read one line and return it or store it in the var"
+ },
+ { .cmd = "puts",
+ .args = "?-nonewline? str",
+ .function = aio_cmd_puts,
+ .minargs = 1,
+ .maxargs = 2,
+ .description = "Write the string, with newline unless -nonewline"
+ },
+ { .cmd = "flush",
+ .function = aio_cmd_flush,
+ .description = "Flush the stream"
+ },
+ { .cmd = "eof",
+ .function = aio_cmd_eof,
+ .description = "Returns 1 if stream is at eof"
+ },
+ { .cmd = "close",
+ .flags = JIM_MODFLAG_FULLARGV,
+ .function = aio_cmd_close,
+ .description = "Closes the stream"
+ },
+ { .cmd = "seek",
+ .args = "offset ?start|current|end",
+ .function = aio_cmd_seek,
+ .minargs = 1,
+ .maxargs = 2,
+ .description = "Seeks in the stream (default 'current')"
+ },
+ { .cmd = "tell",
+ .function = aio_cmd_tell,
+ .description = "Returns the current seek position"
+ },
+ { .cmd = "ndelay",
+ .args = "?0|1?",
+ .function = aio_cmd_ndelay,
+ .minargs = 0,
+ .maxargs = 1,
+ .description = "Set O_NDELAY (if arg). Returns current/new setting."
+ },
+ { .cmd = "accept",
+ .function = aio_cmd_accept,
+ .description = "Server socket only: Accept a connection and return stream"
+ },
+#ifdef with_jim_ext_eventloop
+ { .cmd = "readable",
+ .args = "?readable-script ?eof-script??",
+ .minargs = 0,
+ .maxargs = 2,
+ .function = aio_cmd_readable,
+ .description = "Returns script, or invoke readable-script when readable, eof-script on eof, {} to remove",
+ },
+ { .cmd = "writable",
+ .args = "?writable-script?",
+ .minargs = 0,
+ .maxargs = 1,
+ .function = aio_cmd_writable,
+ .description = "Returns script, or invoke writable-script when writable, {} to remove",
+ },
+ { .cmd = "onexception",
+ .args = "?exception-script?",
+ .minargs = 0,
+ .maxargs = 1,
+ .function = aio_cmd_onexception,
+ .description = "Returns script, or invoke exception-script when oob data, {} to remove",
+ },
+#endif
+ { 0 }
+};
+
+static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ return Jim_CallSubCmd(interp, Jim_ParseSubCmd(interp, command_table, argc, argv), argc, argv);
+}
+
static int JimAioOpenCommand(Jim_Interp *interp, int argc,
Jim_Obj *const *argv)
{
@@ -514,7 +615,7 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
af->rEvent = NULL;
af->wEvent = NULL;
af->eEvent = NULL;
- Jim_CreateCommand(interp, cmdname, JimAioHandlerCommand, af, JimAioDelProc);
+ Jim_CreateCommand(interp, cmdname, JimAioSubCmdProc, af, JimAioDelProc);
Jim_SetResultString(interp, cmdname, -1);
return JIM_OK;
}
@@ -564,6 +665,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc,
struct sockaddr_in sa;
struct hostent *he;
int res;
+ int on = 1;
if (argc <= 2 ) {
Jim_WrongNumArgs(interp, 1, argv, "sockspec ?script?");
@@ -588,11 +690,11 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc,
he = gethostbyname(sthost);
/* FIX!!!! this still results in null pointer exception here.
FIXED!!!! debug output but no JIM_ERR done UK.
+ */
if (!he) {
Jim_SetResultString(interp,hstrerror(h_errno),-1);
return JIM_ERR;
}
- */
sock = socket(PF_INET,SOCK_STREAM,0);
switch (socktype) {
@@ -615,6 +717,10 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc,
sa.sin_family= he->h_addrtype;
bcopy(he->h_addr,(char *)&sa.sin_addr,he->h_length); /* set address */
sa.sin_port = htons(port);
+
+ /* Enable address reuse */
+ setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+
res = bind(sock,(struct sockaddr*)&sa,sizeof(sa));
if (res) {
close(sock);
@@ -649,36 +755,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc,
af->wEvent = NULL;
af->eEvent = NULL;
sprintf(buf, hdlfmt, fileId);
- Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
- Jim_SetResultString(interp, buf, -1);
- return JIM_OK;
-}
-
-static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af )
-{
- int sock;
- socklen_t addrlen = sizeof(struct sockaddr_in);
- AioFile *af;
- char buf[AIO_CMD_LEN];
- long fileId;
- sock = accept(serv_af->fd,(struct sockaddr*)&serv_af->sa,&addrlen);
- if (sock < 0)
- return JIM_ERR;
-
- /* Get the next file id */
- fileId = Jim_GetId(interp);
-
- /* Create the file command */
- af = Jim_Alloc(sizeof(*af));
- af->fd = sock;
- af->fp = fdopen(sock,"r+");
- af->OpenFlags = AIO_FDOPEN;
- af->flags = fcntl(af->fd,F_GETFL);
- af->rEvent = NULL;
- af->wEvent = NULL;
- af->eEvent = NULL;
- sprintf(buf, "aio.sockstream%ld", fileId);
- Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc);
+ Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
Jim_SetResultString(interp, buf, -1);
return JIM_OK;
}
@@ -687,7 +764,7 @@ FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
{
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
- if (cmdPtr && cmdPtr->cmdProc == JimAioHandlerCommand) {
+ if (cmdPtr && cmdPtr->cmdProc == JimAioSubCmdProc) {
return ((AioFile *)cmdPtr->privData)->fp;
}
return NULL;
@@ -774,6 +851,3 @@ Jim_aioInit(Jim_Interp *interp)
return JIM_OK;
}
-
-// end
-
diff --git a/jim-eventloop.c b/jim-eventloop.c
index 8201d73..a024a9f 100644
--- a/jim-eventloop.c
+++ b/jim-eventloop.c
@@ -277,8 +277,7 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
while (fe != NULL) {
int fd = fileno(fe->handle);
- if (fe->mask & JIM_EVENT_READABLE)
- FD_SET(fd, &rfds);
+ if (fe->mask & JIM_EVENT_READABLE) FD_SET(fd, &rfds);
if (fe->mask & JIM_EVENT_WRITABLE) FD_SET(fd, &wfds);
if (fe->mask & JIM_EVENT_EXCEPTION) FD_SET(fd, &efds);
if (maxfd < fd) maxfd = fd;
@@ -336,11 +335,12 @@ int Jim_ProcessEvents(Jim_Interp *interp, int flags)
{
int mask = 0;
- if (fe->mask & JIM_EVENT_READABLE && FD_ISSET(fd, &rfds)) {
+ if ((fe->mask & JIM_EVENT_READABLE) && FD_ISSET(fd, &rfds)) {
mask |= JIM_EVENT_READABLE;
- if ((fe->mask & JIM_EVENT_FEOF) && feof(fe->handle))
- mask |= JIM_EVENT_FEOF;
- }
+ if ((fe->mask & JIM_EVENT_FEOF) && feof(fe->handle)) {
+ mask |= JIM_EVENT_FEOF;
+ }
+ }
if (fe->mask & JIM_EVENT_WRITABLE && FD_ISSET(fd, &wfds))
mask |= JIM_EVENT_WRITABLE;
if (fe->mask & JIM_EVENT_EXCEPTION && FD_ISSET(fd, &efds))
diff --git a/jim-file.c b/jim-file.c
index 547efdf..4fb5b43 100644
--- a/jim-file.c
+++ b/jim-file.c
@@ -658,7 +658,8 @@ static int Jim_PwdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
const int cwd_len=2048;
char *cwd=malloc(cwd_len);
- if (getcwd(cwd, cwd_len) != 0) {
+ if (getcwd(cwd, cwd_len) == NULL) {
+ Jim_SetResultString(interp, "Failed to get pwd", -1);
return JIM_ERR;
}
diff --git a/jim-subcmd.c b/jim-subcmd.c
index 044c8c9..3859606 100644
--- a/jim-subcmd.c
+++ b/jim-subcmd.c
@@ -175,7 +175,12 @@ int Jim_CallSubCmd(Jim_Interp *interp, const jim_subcmd_type *ct, int argc, Jim_
int ret = JIM_ERR;
if (ct) {
- ret = ct->function(interp, argc - 2, argv + 2);
+ if (ct->flags & JIM_MODFLAG_FULLARGV) {
+ ret = ct->function(interp, argc, argv);
+ }
+ else {
+ ret = ct->function(interp, argc - 2, argv + 2);
+ }
if (ret < 0) {
Jim_SetResultString(interp, "wrong # args: should be \"", -1);
add_subcmd_usage(interp, ct, argc, argv);
diff --git a/jim-subcmd.h b/jim-subcmd.h
index 973d80c..4525837 100644
--- a/jim-subcmd.h
+++ b/jim-subcmd.h
@@ -6,7 +6,8 @@
#include <jim.h>
-#define JIM_MODFLAG_HIDDEN 0x0001 /* Don't show the subcommand in usage or commands */
+#define JIM_MODFLAG_HIDDEN 0x0001 /* Don't show the subcommand in usage or commands */
+#define JIM_MODFLAG_FULLARGV 0x0001 /* Subcmd proc gets called with full argv */
/* Custom flags start at 0x0100 */
diff --git a/jim.c b/jim.c
index a794b03..68f414a 100644
--- a/jim.c
+++ b/jim.c
@@ -1798,8 +1798,8 @@ void Jim_FreeObj(Jim_Interp *interp, Jim_Obj *objPtr)
{
/* Check if the object was already freed, panic. */
if (objPtr->refCount != 0) {
- Jim_Panic(interp,"!!!Object %p freed with bad refcount %d", objPtr,
- objPtr->refCount);
+ Jim_Panic(interp,"!!!Object %p freed with bad refcount %d, type=%s", objPtr,
+ objPtr->refCount, objPtr->typePtr ? objPtr->typePtr->name : "<none>");
}
/* Free the internal representation */
Jim_FreeIntRep(interp, objPtr);
diff --git a/tcltests/runtests b/tcltests/runtests
index df0faba..e3ce73b 100755
--- a/tcltests/runtests
+++ b/tcltests/runtests
@@ -19,14 +19,27 @@ proc verbose {msg} {
set verbose [string equal [lindex $argv 0] "-v"]
foreach i [glob test_*.tcl] {
- puts -nonewline "$i..."
- flush stdout
- if {[catch {source $i} error]} {
+ if {$verbose} {
+ puts "======= $i ======="
+ } else {
+ puts -nonewline "$i..."
+ flush stdout
+ }
+ set rc [catch {source $i} result]
+ if {$verbose} {
+ puts -nonewline "$i..."
+ }
+ if {$rc} {
puts "failed"
if {$verbose} {
- puts $error
+ puts $result
}
+ } elseif {$result ne ""} {
+ puts $result
} else {
puts "ok"
}
+ if {$verbose} {
+ puts ""
+ }
}
diff --git a/tcltests/test_bio.tcl b/tcltests/test_bio.tcl
index addcbeb..16a40ae 100644
--- a/tcltests/test_bio.tcl
+++ b/tcltests/test_bio.tcl
@@ -1,3 +1,7 @@
+if {[info commands bio] eq ""} {
+ return "noimpl"
+}
+
proc copy_binary_file {infile outfile} {
set in [open $infile r]
set out [open $outfile w]
diff --git a/tcltests/test_read.tcl b/tcltests/test_read.tcl
index a142128..f7d4c29 100644
--- a/tcltests/test_read.tcl
+++ b/tcltests/test_read.tcl
@@ -7,7 +7,8 @@ signal handle SIGALRM
catch -signal {
alarm 0.5
while {1} {
- incr count [bio read -hex $f buf 1]
+ incr count [string length [read $f 100]]
+ #incr count [bio read -hex $f buf 1]
}
alarm 0
signal default SIGALRM
@@ -18,3 +19,5 @@ verbose "Read $count bytes in 0.5 seconds: Got $error"
# Kill it off
#kill -TERM [pid $f]
catch {close $f}
+
+return