diff options
author | Steve Bennett <steveb@workware.net.au> | 2009-07-28 15:46:40 +1000 |
---|---|---|
committer | Steve Bennett <steveb@workware.net.au> | 2010-10-15 10:11:02 +1000 |
commit | 462954132b1830a7e470436bf751fe8e86291c72 (patch) | |
tree | e4a917e94147dda69ecf9b74df2a9f2605edc99c | |
parent | 981bd5980a5f2ef5e1a527dd3bd90d9f6cfaa632 (diff) | |
download | jimtcl-462954132b1830a7e470436bf751fe8e86291c72.zip jimtcl-462954132b1830a7e470436bf751fe8e86291c72.tar.gz jimtcl-462954132b1830a7e470436bf751fe8e86291c72.tar.bz2 |
Lots of improvements
jim
---
Add a unique id facility to jim (Jim_GetId())
Remove unused jim_vasprintf(), Jim_AppendString_sprintf()
Remove duplicate output in Jim_Panic()
Add support for catch -signal
aio
---
Use this for aio handles
aio automatically creates stdin, stdout and stderr channels
Jim_AioFilehandle() returns the 'FILE *' filehandle for a channel
If JIM_TCL_COMPAT is set, create top level open, close, read, puts, etc.
load
----
load core command split out into jim-load.c
package
-------
package core command split out into jim-package.c
added 'package list'
posix
-----
Remove os.sleep, os.usleep, os.sethostname, os.signal, pit, Jpit
Most of these are in 'signal'
-rw-r--r-- | jim-aio.c | 137 | ||||
-rw-r--r-- | jim-bio.c | 273 | ||||
-rw-r--r-- | jim-load.c | 16 | ||||
-rw-r--r-- | jim-package.c | 72 | ||||
-rw-r--r-- | jim-posix.c | 294 | ||||
-rw-r--r-- | jim-signal.c | 492 | ||||
-rw-r--r-- | jim.c | 649 | ||||
-rw-r--r-- | jim.h | 21 |
8 files changed, 1256 insertions, 698 deletions
@@ -117,15 +117,15 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData) if (!af->OpenFlags == AIO_FDOPEN) // fp = fdopen(fd) !! close(af->fd); if (af->rEvent) { // remove existing EventHandlers - Jim_DeleteFileHandler(interp,af->fp); - Jim_DecrRefCount(interp,af->rEvent); + Jim_DeleteFileHandler(interp,af->fp); + Jim_DecrRefCount(interp,af->rEvent); } if (af->wEvent) { - Jim_DeleteFileHandler(interp,af->fp); + Jim_DeleteFileHandler(interp,af->fp); Jim_DecrRefCount(interp,af->wEvent); } if (af->eEvent) { - Jim_DeleteFileHandler(interp,af->fp); + Jim_DeleteFileHandler(interp,af->fp); Jim_DecrRefCount(interp,af->eEvent); } Jim_Free(af); @@ -154,7 +154,7 @@ static int JimAioHandlerCommand(Jim_Interp *interp, int argc, OPT_FLUSH, OPT_EOF, OPT_NDELAY, OPT_READABLE, OPT_WRITABLE, OPT_EXCEPTION, - OPT_ACCEPT + OPT_ACCEPT, }; if (argc < 2) { @@ -451,9 +451,7 @@ static int JimAioHandlerCommand(Jim_Interp *interp, int argc, return JIM_ERR; } } else if (option == OPT_ACCEPT) { - int ret; - ret = JimAioAcceptHelper(interp,af); - return (ret); + return JimAioAcceptHelper(interp,af); } return JIM_OK; } @@ -465,12 +463,12 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, AioFile *af; char buf[AIO_CMD_LEN]; const char *mode = "r"; - Jim_Obj *objPtr; long fileId; const char *options[] = {"input", "output", "error", NULL}; enum {OPT_INPUT, OPT_OUTPUT, OPT_ERROR}; int OpenFlags = 0; int modeLen; + const char *cmdname = buf; if (argc != 2 && argc != 3) { Jim_WrongNumArgs(interp, 1, argv, "filename ?mode?"); @@ -486,9 +484,9 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, return JIM_ERR; OpenFlags |= AIO_KEEPOPEN; switch (option) { - case OPT_INPUT: fp = stdin; break; - case OPT_OUTPUT: fp = stdout; break; - case OPT_ERROR: fp = stderr; break; + case OPT_INPUT: fp = stdin; cmdname = "stdin"; break; + case OPT_OUTPUT: fp = stdout; cmdname = "stdout"; break; + case OPT_ERROR: fp = stderr; cmdname = "stderr"; break; default: fp = NULL; Jim_Panic(interp,"default reached in JimAioOpenCommand()"); break; } @@ -498,14 +496,10 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, JimAioSetError(interp); return JIM_ERR; } + /* Get the next file id */ + fileId = Jim_GetId(interp); + sprintf(buf, "aio.handle%ld", fileId); } - /* Get the next file id */ - if (Jim_EvalGlobal(interp, - "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK) - return JIM_ERR; - objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG); - if (objPtr == NULL) return JIM_ERR; - if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR; /* Create the file command */ af = Jim_Alloc(sizeof(*af)); @@ -516,9 +510,8 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc, af->rEvent = NULL; af->wEvent = NULL; af->eEvent = NULL; - sprintf(buf, "aio.handle%ld", fileId); - Jim_CreateCommand(interp, buf, JimAioHandlerCommand, af, JimAioDelProc); - Jim_SetResultString(interp, buf, -1); + Jim_CreateCommand(interp, cmdname, JimAioHandlerCommand, af, JimAioDelProc); + Jim_SetResultString(interp, cmdname, -1); return JIM_OK; } @@ -528,8 +521,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, FILE *fp; AioFile *af; char buf[AIO_CMD_LEN]; - char *hdlfmt = "unknown"; - Jim_Obj *objPtr; + char *hdlfmt = "aio.unknown%ld"; long fileId; const char *socktypes[] = { "file", @@ -641,12 +633,7 @@ static int JimAioSockCommand(Jim_Interp *interp, int argc, return JIM_ERR; } /* Get the next file id */ - if (Jim_EvalGlobal(interp, - "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK) - return JIM_ERR; - objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG); - if (objPtr == NULL) return JIM_ERR; - if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR; + fileId = Jim_GetId(interp); /* Create the file command */ af = Jim_Alloc(sizeof(*af)); @@ -669,19 +656,13 @@ static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af ) int addrlen = sizeof(struct sockaddr_in); AioFile *af; char buf[AIO_CMD_LEN]; - Jim_Obj *objPtr; long fileId; sock = accept(serv_af->fd,(struct sockaddr*)&serv_af->sa,&addrlen); if (sock < 0) return JIM_ERR; /* Get the next file id */ - if (Jim_EvalGlobal(interp, - "if {[catch {incr aio.fileId}]} {set aio.fileId 0}") != JIM_OK) - return JIM_ERR; - objPtr = Jim_GetGlobalVariableStr(interp, "aio.fileId", JIM_ERRMSG); - if (objPtr == NULL) return JIM_ERR; - if (Jim_GetLong(interp, objPtr, &fileId) != JIM_OK) return JIM_ERR; + fileId = Jim_GetId(interp); /* Create the file command */ af = Jim_Alloc(sizeof(*af)); @@ -698,6 +679,79 @@ static int JimAioAcceptHelper(Jim_Interp *interp, AioFile *serv_af ) return JIM_OK; } +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command) +{ + Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG); + + if (cmdPtr && cmdPtr->cmdProc == JimAioHandlerCommand) { + return ((AioFile *)cmdPtr->privData)->fp; + } + return NULL; +} + +#ifdef JIM_TCL_COMPAT +static int JimAioTclCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj **newargv = Jim_Alloc(sizeof(Jim_Obj*)*argc); + int ret; + int i; + + /* cmd channel ?args? */ + newargv[0] = argv[1]; + newargv[1] = argv[0]; + + for (i = 2; i < argc; i++) { + newargv[i] = argv[i]; + } + + ret = Jim_EvalObjVector(interp, argc, newargv); + + Jim_Free(newargv); + + return ret; +} + +static int JimAioPutsCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + Jim_Obj *newargv[4]; + + int off = 1; + + /* "puts" */ + newargv[off++] = argv[0]; + + /* puts ?-nonewline? ?channel? msg */ + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) { + newargv[off++] = argv[1]; + argv++; + argc--; + } + + if (argc == 2) { + /* Missing channel, so use stdout */ + newargv[0] = Jim_NewStringObj(interp, "stdout", -1); + newargv[off++] = argv[1]; + } + else { + newargv[0] = argv[1]; + newargv[off++] = argv[2]; + } + return Jim_EvalObjVector(interp, off, newargv); +} + +static void JimAioTclCompat(Jim_Interp *interp) +{ + static const char *tclcmds[] = { "read", "gets", "flush", "close", "eof", "seek", "tell", 0}; + int i; + + for (i = 0; tclcmds[i]; i++) { + Jim_CreateCommand(interp, tclcmds[i], JimAioTclCmd, NULL, NULL); + } + Jim_CreateCommand(interp, "puts", JimAioPutsCmd, NULL, NULL); + Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL); +} +#endif + int Jim_aioInit(Jim_Interp *interp) { @@ -705,6 +759,15 @@ Jim_aioInit(Jim_Interp *interp) return JIM_ERR; Jim_CreateCommand(interp, "aio.open", JimAioOpenCommand, NULL, NULL); Jim_CreateCommand(interp, "aio.socket", JimAioSockCommand, NULL, NULL); + + /* Takeover stdin, stdout and stderr */ + Jim_EvalGlobal(interp, + "aio.open standard input; aio.open standard output; aio.open standard error"); + +#ifdef JIM_TCL_COMPAT + JimAioTclCompat(interp); +#endif + return JIM_OK; } diff --git a/jim-bio.c b/jim-bio.c new file mode 100644 index 0000000..93696e1 --- /dev/null +++ b/jim-bio.c @@ -0,0 +1,273 @@ +/* + * jim-bio.c + * + * Implements the bio command for binary I/O + * + * bio read ?-hex? fd var length + * + * Reads 'length' bytes of binary data from 'fd' and stores an encoded string + * in 'var' so that the string contains no internal null characters. + * + * Returns the number of (original) chars read, which may be short if EOF is reached. + * + * bio write ?-hex? fd encoded + * + * Writes the binary-encoded string 'encoded' to 'fd' + * + * Returns the number of chars written (if no error) + * + * For the default binary encoding: + * - 0x00 -> 0x01, 0x30 + * - 0x01 -> 0x01, 0x31 + * + * Alternatively, if -hex is specified, the data is read and written as ascii hex + */ + +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <time.h> + +#include <jim.h> +#include <jim-subcmd.h> + +static int hex2char(const char *hex) +{ + int value; + value = (hex[0] >= 'A' ? ((hex[0] & 0xdf) - 'A') + 10 : (hex[0] - '0')); + value *= 16; + value += (hex[1] >= 'A' ? ((hex[1] & 0xdf) - 'A') + 10 : (hex[1] - '0')); + return value; +} + +static void char2hex(int c, char hex[2]) +{ + hex[1] = (c & 0x0F) >= 0x0A ? (c & 0x0F) + 'A' - 10 : (c & 0x0F) + '0'; + c /= 16; + hex[0] = (c & 0x0F) >= 0x0A ? (c & 0x0F) + 'A' - 10 : (c & 0x0F) + '0'; +} + +/** + * Modelled on Jim_ReadCmd + * + */ +static int bio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + char buf[130]; + int count = 0; + long len; + int hex = 0; + int total = 0; + FILE *fh; + + if (Jim_CompareStringImmediate(interp, argv[0], "-hex")) { + hex++; + argv++; + argc--; + } + else if (argc == 4) { + return -1; + } + + fh = Jim_AioFilehandle(interp, argv[0]); + + if (!fh) { + return JIM_ERR; + } + + if (Jim_GetLong(interp, argv[2], &len) != JIM_OK) { + return JIM_ERR; + } + + Jim_Obj *result = Jim_NewStringObj(interp, "", 0); + + /* Read one char at a time, escaping 0x00 and 0xFF as necessary */ + while (len > 0) { + int ch = fgetc(fh); + if (ch == EOF) { + break; + } + total++; + + if (hex) { + char2hex(ch, buf + count); + count += 2; + } + else { + if (ch == 0 || ch == 1) { + buf[count++] = 1; + ch = ch + '0'; + } + buf[count++] = ch; + } + + /* Allow space for the null termination, plus escaping of one char */ + if (count >= sizeof(buf) - 2) { + /* Buffer is full, so append it */ + Jim_AppendString(interp, result, buf, count); + + count = 0; + } + len--; + } + + if (ferror(fh)) { + Jim_SetResultString(interp, "error during read", -1); + clearerr(fh); + return JIM_ERR; + } + + Jim_AppendString(interp, result, buf, count); + + if (Jim_SetVariable(interp, argv[1], result) != JIM_OK) { + return JIM_ERR; + } + + Jim_SetResultInt(interp, total); + + return JIM_OK; +} + +#if 0 +static int bio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + OpenFile *infilePtr; + OpenFile *outfilePtr; + int count = 0; + int maxlen = 0; + + if (TclGetOpenFile(interp, argv[0], &infilePtr) != JIM_OK) { + return TCL_ERROR; + } + if (!infilePtr->readable) { + Jim_AppendResult(interp, "\"", argv[0], + "\" wasn't opened for reading", (char *) NULL); + return TCL_ERROR; + } + if (TclGetOpenFile(interp, argv[1], &outfilePtr) != JIM_OK) { + return TCL_ERROR; + } + if (!outfilePtr->writable) { + Jim_AppendResult(interp, "\"", argv[1], + "\" wasn't opened for writing", (char *) NULL); + return TCL_ERROR; + } + + if (argc == 3) { + if (Jim_GetInt(interp, argv[2], &maxlen) != JIM_OK) { + return TCL_ERROR; + } + } + + while (maxlen == 0 || count < maxlen) { + int ch = fgetc(infilePtr->f); + if (ch == EOF || fputc(ch, outfilePtr->f) == EOF) { + break; + } + count++; + } + + if (ferror(infilePtr->f)) { + Jim_AppendResult(interp, "error reading \"", argv[0], "\": ", Jim_UnixError(interp), 0); + clearerr(infilePtr->f); + return TCL_ERROR; + } + + if (ferror(outfilePtr->f)) { + Jim_AppendResult(interp, "error writing \"", argv[0], "\": ", Jim_UnixError(interp), 0); + clearerr(outfilePtr->f); + return TCL_ERROR; + } + + Jim_SetIntResult(interp, count); + + return JIM_OK; +} +#endif + +static int bio_cmd_write(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + FILE *fh; + const char *pt; + int hex = 0; + long total = 0; + + + if (Jim_CompareStringImmediate(interp, argv[0], "-hex")) { + hex++; + argv++; + argc--; + } + else if (argc == 3) { + return -1; + } + + fh = Jim_AioFilehandle(interp, argv[0]); + + for (pt = Jim_GetString(argv[1], NULL); *pt; pt++) { + int ch; + + if (hex) { + ch = hex2char(pt); + pt++; + } + else { + ch = *pt; + if (ch == 1) { + pt++; + ch = *pt - '0'; + } + } + if (fputc(ch, fh) == EOF) { + break; + } + total++; + } + + if (ferror(fh)) { + Jim_SetResultString(interp, "error during write", -1); + clearerr(fh); + return JIM_ERR; + } + + Jim_SetResultInt(interp, total); + + return JIM_OK; +} + +static const jim_subcmd_type command_table[] = { + { .cmd = "read", + .function = bio_cmd_read, + .args = "?-hex? fd var numbytes", + .minargs = 3, + .maxargs = 4, + .description = "Read binary bytes as an encoded string" + }, + { .cmd = "write", + .function = bio_cmd_write, + .args = "?-hex? fd buf", + .minargs = 2, + .maxargs = 3, + .description = "Write an encoded string as binary bytes" + }, +#if 0 + { .cmd = "copy", + .function = bio_cmd_copy, + .args = "fromfd tofd ?bytes?", + .minargs = 2, + .maxargs = 3, + .description = "Read from one fd and write to another" + }, +#endif + { 0 } +}; + +int +Jim_bioInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "bio", "1.0", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + Jim_CreateCommand(interp, "bio", Jim_SubCmdProc, (void *)command_table, NULL); + return JIM_OK; +} @@ -116,3 +116,19 @@ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName) } #endif/* JIM_DYNLIB */ +/* [load] */ +static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, + Jim_Obj *const *argv) +{ + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "libaryFile"); + return JIM_ERR; + } + return Jim_LoadLibrary(interp, Jim_GetString(argv[1], NULL)); +} + +int Jim_loadInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "load", Jim_LoadCoreCommand, NULL, NULL); + return JIM_OK; +} diff --git a/jim-package.c b/jim-package.c index 48976c0..4474381 100644 --- a/jim-package.c +++ b/jim-package.c @@ -28,6 +28,24 @@ int Jim_PackageProvide(Jim_Interp *interp, const char *name, const char *ver, return JIM_OK; } +static int Jim_PackageList(Jim_Interp *interp) +{ + Jim_HashTableIterator *htiter; + Jim_HashEntry *he; + Jim_Obj *listObjPtr = Jim_NewListObj(interp, NULL, 0); + + htiter = Jim_GetHashTableIterator(&interp->packages); + while ((he = Jim_NextHashEntry(htiter)) != NULL) { + Jim_ListAppendElement(interp, listObjPtr, + Jim_NewStringObj(interp, he->key, -1)); + } + Jim_FreeHashTableIterator(htiter); + + Jim_SetResult(interp, listObjPtr); + + return JIM_OK; +} + static char *JimFindPackage(Jim_Interp *interp, char **prefixes, int prefixc, const char *pkgName) { @@ -135,3 +153,57 @@ const char *Jim_PackageRequire(Jim_Interp *interp, const char *name, } } +/* [package] */ +int Jim_PackageCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int option; + const char *options[] = { + "require", "provide", "list", NULL + }; + enum {OPT_REQUIRE, OPT_PROVIDE, OPT_LIST}; + + if (argc < 2) { + Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); + return JIM_ERR; + } + if (Jim_GetEnum(interp, argv[1], options, &option, "option", + JIM_ERRMSG) != JIM_OK) + return JIM_ERR; + + if (option == OPT_REQUIRE) { + int exact = 0; + const char *ver; + + if (Jim_CompareStringImmediate(interp, argv[2], "-exact")) { + exact = 1; + argv++; + argc--; + } + if (argc != 3 && argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "?-exact? package ?version?"); + return JIM_ERR; + } + ver = Jim_PackageRequire(interp, Jim_GetString(argv[2], NULL), + argc == 4 ? Jim_GetString(argv[3], NULL) : "", + JIM_ERRMSG); + if (ver == NULL) + return JIM_ERR_ADDSTACK; + Jim_SetResultString(interp, ver, -1); + } else if (option == OPT_PROVIDE) { + if (argc != 4) { + Jim_WrongNumArgs(interp, 2, argv, "package version"); + return JIM_ERR; + } + return Jim_PackageProvide(interp, Jim_GetString(argv[2], NULL), + Jim_GetString(argv[3], NULL), JIM_ERRMSG); + } else if (option == OPT_LIST) { + return Jim_PackageList(interp); + } + return JIM_OK; +} + +int Jim_packageInit(Jim_Interp *interp) +{ + Jim_CreateCommand(interp, "package", Jim_PackageCoreCommand, NULL, NULL); + return JIM_OK; +} diff --git a/jim-posix.c b/jim-posix.c index f280f3e..9a81a55 100644 --- a/jim-posix.c +++ b/jim-posix.c @@ -50,21 +50,6 @@ static int Jim_PosixForkCommand(Jim_Interp *interp, int argc, return JIM_OK; } -static int Jim_PosixSleepCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - long longValue; - - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "?seconds?"); - return JIM_ERR; - } - if (Jim_GetLong(interp, argv[1], &longValue) != JIM_OK) - return JIM_ERR; - sleep(longValue); - return JIM_OK; -} - static int Jim_PosixGetidsCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { @@ -103,292 +88,13 @@ static int Jim_PosixGethostnameCommand(Jim_Interp *interp, int argc, return JIM_OK; } -static int Jim_PosixSethostnameCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - const char *hostname; - int len; - - if (argc != 2) { - Jim_WrongNumArgs(interp, 1, argv, "hostname"); - return JIM_ERR; - } - hostname = Jim_GetString(argv[1], &len); - if (sethostname(hostname, len) == -1) { - Jim_PosixSetError(interp); - return JIM_ERR; - } - return JIM_OK; -} -// added Commands, some linux specific - -// uses POSIX.1b -#define S_NS 1000000000 -#define S_US 1000000 -#define MSNS 1000000 -#define USNS 1000 -#define NSNS 1 - -static int Jim_LinuxUSleepCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - int mult = NSNS ; - double floatValue ; - const char *units ; - long long delay ; - int len ; - struct timespec tv; - - switch (argc) { - case 3: - units = Jim_GetString(argv[2], &len); - if (units == NULL) - return JIM_ERR; - switch (*units) { - case 's': mult = S_NS; break; - case 'm': mult = MSNS; break; - case 'u': mult = USNS; break; - case 'n': mult = NSNS; break; - default: - Jim_WrongNumArgs(interp, 1, argv, "arg3: ms us ns or empty"); - return JIM_ERR; - } - // fallthrough - case 2: if (Jim_GetDouble(interp, argv[1], &floatValue) != JIM_OK) - return JIM_ERR; - delay = (long long)(floatValue * mult); - break; - default: - Jim_WrongNumArgs(interp, 1, argv, "?useconds?"); - return JIM_ERR; - } - tv.tv_sec = delay / S_NS; - tv.tv_nsec = delay % S_NS; - fprintf(stderr,"delay: %lld mult: %d sec: %ld ns: %ld\n", delay, mult, tv.tv_sec,tv.tv_nsec ); - nanosleep(&tv,NULL); - return JIM_OK; -} - -static int Jim_PointInTimeCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - struct timezone tz = { 0, 0 }; - double pit ; - struct timeval tv; - - gettimeofday(&tv,&tz); - pit = (double)tv.tv_usec; - pit /= (double)S_US; - pit +=(double)tv.tv_sec; - - Jim_SetResult(interp, Jim_NewDoubleObj(interp, pit)); - return JIM_OK; -} - -static int Jim_PointInTimeJulianCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - struct timezone tz = { 0, 0 }; - double pit ; - struct timeval tv; - - gettimeofday(&tv,&tz); - pit = (double)tv.tv_usec; - pit /= (double)S_US; - pit += (double)tv.tv_sec; - pit /= (double)( 60 * 60 * 24 ); - pit += 2440587.5; - - Jim_SetResult(interp, Jim_NewDoubleObj(interp, pit)); - return JIM_OK; -} - -#if 0 -// signal stuff -// signal <signame> - - static const char *signames[] = { - "SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", - "SIGABRT", "SIGFPE", "SIGKILL", "SIGSEGV", - "SIGPIPE", "SIGALRM", "SIGTERM", - "SIGUSR1", "SIGUSR2", - "SIGCHLD", "SIGCONT", "SIGSTOP", - "SIGTSTP", "SIGTTIN" "SIGTTOU", - "SIGBUS", -#ifdef SIGPOLL - "SIGPOLL", -#endif - "SIGPROF", "SIGSYS", - "SIGTRAP", "SIGURG", "SIGVTALRM", "SIGXCPU", - "SIGXFSZ", - "SIGIOT", -#ifdef SIGEMT - "SIGEMT", -#endif - "SIGSTKFLT", "SIGIO", - "SIGCLD", "SIGPWR", -#ifdef SIGINFO - "SIGINFO", -#endif -#ifdef SIGLOST - "SIGLOST", -#endif - "SIGWINCH", "SIGUNUSED", - "SIGRT32", "SIGRT33", "SIGRT34", "SIGRT35", - "SIGRT36", "SIGRT37", "SIGRT38", "SIGRT39", - NULL - } ; -static int signums[] = { - SIGHUP, SIGINT, SIGQUIT, SIGILL, - SIGABRT, SIGFPE, SIGKILL, SIGSEGV, - SIGPIPE, SIGALRM, SIGTERM, - SIGUSR1, SIGUSR2, - SIGCHLD, SIGCONT, SIGSTOP, - SIGTSTP, SIGTTIN, SIGTTOU, - SIGBUS, -#ifdef SIGPOLL - SIGPOLL, -#endif - SIGPROF, SIGSYS, - SIGTRAP, SIGURG, SIGVTALRM, SIGXCPU, - SIGXFSZ, - SIGIOT, -#ifdef SIGEMT - SIGEMT, -#endif - SIGSTKFLT, SIGIO, - SIGCLD, SIGPWR, -#ifdef SIGINFO - SIGINFO, -#endif -#ifdef SIGLOST - SIGLOST, -#endif - SIGWINCH, SIGUNUSED, -#ifdef SIGRT - SIGRT32, SIGRT33, SIGRT34, SIGRT35, - SIGRT36, SIGRT37, SIGRT38, SIGRT39, -#endif - 0 - } ; - -#if 0 -enum { - HUP, INT, QUIT, ILL, - ABRT, FPE, KILL, SEGV, - PIPE, ALRM, TERM, - USR1, USR2, - CHLD, CONT, STOP, - TSTP, TTIN, TTOU, - BUS, POLL, PROF, SYS, - TRAP, URG, VTALRM, XCPU, - XFSZ, - IOT, -#ifdef SIGEMT - EMT, -#endif - STKFLT, IO, - CLD, PWR, -#ifdef SIGINFO - INFO, -#endif -#ifdef SIGLOST - LOST, -#endif - WINCH, UNUSED, -#ifdef SIGRT - RT32, RT33, RT34, RT35, - RT36, RT37, RT38, RT39, -#endif - ISEND - } ; -#endif -#endif - -static void Jim_Posix_SigHandler(int signal) -{ -#if 0 - int i; - for (i=0; i<sizeof(signums)/sizeof(*signums) && (signums[i] != signal);i++) ; -#endif - //fprintf(stderr,"signal %d %s\n", signal,signames[i]); - fprintf(stderr,"signal %d\n", signal); -} - -typedef void (*sighandler_t)(int); - -static int Jim_PosixSignalCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - int sig; - int signum; - sighandler_t lastaction; - sighandler_t nextaction = SIG_DFL; - const char *op; - int strlen = 0; - - if (argc < 2) { - Jim_WrongNumArgs(interp, 1, argv, "signame ?action ...?"); - return JIM_ERR; - } - if (Jim_GetEnum(interp, argv[1], signames, &sig, "Signal Names", - JIM_ERRMSG) != JIM_OK) - return JIM_ERR; - - signum = signums[sig]; - - switch (argc) { - case 3: - if (op = Jim_GetString(argv[2], &strlen),strlen == 0) { - return JIM_ERR; - } - if (strcmp("default",op) == 0) { - nextaction = SIG_DFL; - } else if (strcmp("ignore",op) == 0) { - nextaction = SIG_IGN; - } else if (strcmp("debug",op) == 0) { - nextaction = Jim_Posix_SigHandler; - } else { - // this is the place to insert a script! UK - } - // fall through to query case: - case 2: - lastaction = signal(signum, nextaction); - if (argc==2) - signal(signum, lastaction); - if (lastaction == SIG_ERR) { - return JIM_ERR; - } - if (lastaction == SIG_DFL) { - Jim_SetResultString(interp, "default", -1); - return JIM_OK; - } - if (lastaction == SIG_IGN) { - Jim_SetResultString(interp, "ignore", -1); - return JIM_OK; - } - Jim_SetResultString(interp, "function", -1); - return JIM_OK; - } - - return JIM_OK; -} - - - // end added int Jim_posixInit(Jim_Interp *interp) { if (Jim_PackageProvide(interp, "posix", "1.0", JIM_ERRMSG) != JIM_OK) return JIM_ERR; Jim_CreateCommand(interp, "os.fork", Jim_PosixForkCommand, NULL, NULL); - Jim_CreateCommand(interp, "os.sleep", Jim_PosixSleepCommand, NULL, NULL); Jim_CreateCommand(interp, "os.getids", Jim_PosixGetidsCommand, NULL, NULL); Jim_CreateCommand(interp, "os.gethostname", Jim_PosixGethostnameCommand, NULL, NULL); - Jim_CreateCommand(interp, "os.sethostname", Jim_PosixSethostnameCommand, NULL, NULL); - Jim_CreateCommand(interp, "os.usleep", Jim_LinuxUSleepCommand, NULL, NULL); - Jim_CreateCommand(interp, "os.signal", Jim_PosixSignalCommand, NULL, NULL); - Jim_CreateCommand(interp, "pit", Jim_PointInTimeCommand, NULL, NULL); - Jim_CreateCommand(interp, "Jpit", Jim_PointInTimeJulianCommand, NULL, NULL); return JIM_OK; } diff --git a/jim-signal.c b/jim-signal.c new file mode 100644 index 0000000..1d21d59 --- /dev/null +++ b/jim-signal.c @@ -0,0 +1,492 @@ +/* + * jim-signal.c + * + */ + +#include <signal.h> +#include <string.h> +#include <ctype.h> +#include <unistd.h> + +#include "jim.h" +#include "jim-subcmd.h" + +#define MAX_SIGNALS 32 + +static int *sigloc; +static unsigned long sigsblocked; +static struct sigaction *sa_old; +static int signal_handling[MAX_SIGNALS]; + +static void signal_handler(int sig) +{ + /* We just remember which signal occurred. Jim_Eval() will + * notice this as soon as it can and throw an error + */ + *sigloc = sig; +} + +static void signal_ignorer(int sig) +{ + /* We just remember which signals occurred */ + sigsblocked |= (1 << sig); +} + +/* + *---------------------------------------------------------------------- + * + * Tcl_SignalId -- + * + * Return a textual identifier for a signal number. + * + * Results: + * This procedure returns a machine-readable textual identifier + * that corresponds to sig. The identifier is the same as the + * #define name in signal.h. + * + * Side effects: + * None. + * + *---------------------------------------------------------------------- + */ + +const char *Jim_SignalId(int sig) +{ + switch (sig) { +#ifdef SIGABRT + case SIGABRT: return "SIGABRT"; +#endif +#ifdef SIGALRM + case SIGALRM: return "SIGALRM"; +#endif +#ifdef SIGBUS + case SIGBUS: return "SIGBUS"; +#endif +#ifdef SIGCHLD + case SIGCHLD: return "SIGCHLD"; +#endif +#if defined(SIGCLD) && (!defined(SIGCHLD) || (SIGCLD != SIGCHLD)) + case SIGCLD: return "SIGCLD"; +#endif +#ifdef SIGCONT + case SIGCONT: return "SIGCONT"; +#endif +#if defined(SIGEMT) && (!defined(SIGXCPU) || (SIGEMT != SIGXCPU)) + case SIGEMT: return "SIGEMT"; +#endif +#ifdef SIGFPE + case SIGFPE: return "SIGFPE"; +#endif +#ifdef SIGHUP + case SIGHUP: return "SIGHUP"; +#endif +#ifdef SIGILL + case SIGILL: return "SIGILL"; +#endif +#ifdef SIGINT + case SIGINT: return "SIGINT"; +#endif +#ifdef SIGIO + case SIGIO: return "SIGIO"; +#endif +#if defined(SIGIOT) && (!defined(SIGABRT) || (SIGIOT != SIGABRT)) + case SIGIOT: return "SIGIOT"; +#endif +#ifdef SIGKILL + case SIGKILL: return "SIGKILL"; +#endif +#if defined(SIGLOST) && (!defined(SIGIOT) || (SIGLOST != SIGIOT)) && (!defined(SIGURG) || (SIGLOST != SIGURG)) + case SIGLOST: return "SIGLOST"; +#endif +#ifdef SIGPIPE + case SIGPIPE: return "SIGPIPE"; +#endif +#if defined(SIGPOLL) && (!defined(SIGIO) || (SIGPOLL != SIGIO)) + case SIGPOLL: return "SIGPOLL"; +#endif +#ifdef SIGPROF + case SIGPROF: return "SIGPROF"; +#endif +#if defined(SIGPWR) && (!defined(SIGXFSZ) || (SIGPWR != SIGXFSZ)) + case SIGPWR: return "SIGPWR"; +#endif +#ifdef SIGQUIT + case SIGQUIT: return "SIGQUIT"; +#endif +#ifdef SIGSEGV + case SIGSEGV: return "SIGSEGV"; +#endif +#ifdef SIGSTOP + case SIGSTOP: return "SIGSTOP"; +#endif +#ifdef SIGSYS + case SIGSYS: return "SIGSYS"; +#endif +#ifdef SIGTERM + case SIGTERM: return "SIGTERM"; +#endif +#ifdef SIGTRAP + case SIGTRAP: return "SIGTRAP"; +#endif +#ifdef SIGTSTP + case SIGTSTP: return "SIGTSTP"; +#endif +#ifdef SIGTTIN + case SIGTTIN: return "SIGTTIN"; +#endif +#ifdef SIGTTOU + case SIGTTOU: return "SIGTTOU"; +#endif +#if defined(SIGURG) && (!defined(SIGIO) || (SIGURG != SIGIO)) + case SIGURG: return "SIGURG"; +#endif +#ifdef SIGUSR1 + case SIGUSR1: return "SIGUSR1"; +#endif +#ifdef SIGUSR2 + case SIGUSR2: return "SIGUSR2"; +#endif +#ifdef SIGVTALRM + case SIGVTALRM: return "SIGVTALRM"; +#endif +#ifdef SIGWINCH + case SIGWINCH: return "SIGWINCH"; +#endif +#ifdef SIGXCPU + case SIGXCPU: return "SIGXCPU"; +#endif +#ifdef SIGXFSZ + case SIGXFSZ: return "SIGXFSZ"; +#endif +#ifdef SIGINFO + case SIGINFO: return "SIGINFO"; +#endif + } + return "unknown signal"; +} + +/** + * Given the name of a signal, returns the signal value if found, + * or returns -1 (and sets an error) if not found. + * We accept -SIGINT, SIGINT, INT or any lowercase version or a number, + * either positive or negative. + */ +static int +find_signal_by_name(Jim_Interp *interp, const char *name) +{ + int i; + const char *pt = name; + + /* Remove optional - and SIG from the front of the name */ + if (*pt == '-') { + pt++; + } + if (strncasecmp(name, "sig", 3) == 0) { + pt += 3; + } + if (isdigit(pt[0])) { + i = atoi(pt); + if (i > 0 && i < MAX_SIGNALS) { + return i; + } + } + else { + for (i = 1; i < MAX_SIGNALS; i++) { + /* Jim_SignalId() returns names such as SIGINT, and + * returns "unknown signal id" if unknown, so this will work + */ + if (strcasecmp(Jim_SignalId(i) + 3, pt) == 0) { + return i; + } + } + } + Jim_SetResultString(interp, "unknown signal ", -1); + Jim_AppendString(interp, Jim_GetResult(interp), name, -1); + + return -1; +} + +#define SIGNAL_ACTION_HANDLE 1 +#define SIGNAL_ACTION_IGNORE -1 +#define SIGNAL_ACTION_DEFAULT 0 + +static int do_signal_cmd(Jim_Interp *interp, int action, int argc, Jim_Obj *const *argv) +{ + struct sigaction sa; + int i; + + if (argc == 0) { + Jim_SetResult(interp, Jim_NewListObj(interp, NULL, 0)); + for (i = 1; i < MAX_SIGNALS; i++) { + if (signal_handling[i] == action) { + /* Add signal name to the list */ + Jim_ListAppendElement(interp, Jim_GetResult(interp), + Jim_NewStringObj(interp, Jim_SignalId(i), -1)); + } + } + return JIM_OK; + } + + /* Make sure we know where to store the signals which occur */ + if (!sigloc) { + sigloc = &interp->signal; + } + + /* Catch all the signals we care about */ + if (action != SIGNAL_ACTION_DEFAULT) { + sa.sa_flags = 0; + sigemptyset(&sa.sa_mask); + if (action == SIGNAL_ACTION_HANDLE) { + sa.sa_handler = signal_handler; + } + else { + sa.sa_handler = signal_ignorer; + } + } + + /* Iterate through the provided signals */ + for (i = 0; i < argc; i++) { + int sig = find_signal_by_name(interp, Jim_GetString(argv[i], NULL)); + if (sig < 0) { + return JIM_ERR; + } + if (action != signal_handling[sig]) { + /* Need to change the action for this signal */ + switch (action) { + case SIGNAL_ACTION_HANDLE: + case SIGNAL_ACTION_IGNORE: + if (signal_handling[sig] == SIGNAL_ACTION_DEFAULT) { + if (!sa_old) { + /* Allocate the structure the first time through */ + sa_old = Jim_Alloc(sizeof(*sa_old) * MAX_SIGNALS); + } + sigaction(sig, &sa, &sa_old[sig]); + } + else { + sigaction(sig, &sa, 0); + } + break; + + case SIGNAL_ACTION_DEFAULT: + /* Restore old handler */ + if (sa_old) { + sigaction(sig, &sa_old[sig], 0); + } + } + signal_handling[sig] = action; + } + } + + return JIM_OK; +} + +static int signal_cmd_handle(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_HANDLE, argc, argv); +} + +static int signal_cmd_ignore(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_IGNORE, argc, argv); +} + +static int signal_cmd_default(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + return do_signal_cmd(interp, SIGNAL_ACTION_DEFAULT, argc, argv); +} + +static int signal_cmd_throw(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig = SIGINT; + if (argc == 1) { + if ((sig = find_signal_by_name(interp, Jim_GetString(argv[0], NULL))) < 0) { + return JIM_ERR; + } + } + + /* Just set the signal */ + interp->signal = sig; + +#if 1 + /* Set the canonical name of the signal as the result */ + Jim_SetResultString(interp, Jim_SignalId(sig), -1); +#endif + + /* And simply say we caught the signal */ + return JIM_SIGNAL; +} + +/* + *----------------------------------------------------------------------------- + * + * Jim_SignalCmd -- + * Implements the TCL signal command: + * signal handle|ignore|default|throw ?signals ...? + * signal throw signal + * + * Specifies which signals are handled by Tcl code. + * If the one of the given signals is caught, it causes a JIM_SIGNAL + * exception to be thrown which can be caught by catch. + * + * Use 'signal ignore' to ignore the signal(s) + * Use 'signal default' to go back to the default behaviour + * Use 'signal throw signal' to raise the given signal + * + * If no arguments are given, returns the list of signals which are being handled + * + * Results: + * Standard TCL results. + * + *----------------------------------------------------------------------------- + */ +static const jim_subcmd_type signal_command_table[] = { + { .cmd = "handle", + .args = "?signals ...?", + .function = signal_cmd_handle, + .minargs = 0, + .maxargs = -1, + .description = "Lists handled signals, or adds to handled signals" + }, + { .cmd = "ignore", + .args = "?signals ...?", + .function = signal_cmd_ignore, + .minargs = 0, + .maxargs = -1, + .description = "Lists ignored signals, or adds to ignored signals" + }, + { .cmd = "default", + .args = "?signals ...?", + .function = signal_cmd_default, + .minargs = 0, + .maxargs = -1, + .description = "Lists defaulted signals, or adds to defaulted signals" + }, + { .cmd = "throw", + .args = "?signal?", + .function = signal_cmd_throw, + .minargs = 0, + .maxargs = 1, + .description = "Raises the given signal (default SIGINT)" + }, + { 0 } +}; + +static int Jim_AlarmCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { +#ifdef HAVE_UALARM + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { + if (t < 10) { + ualarm(t * 1e6, 0); + } + else { + alarm(t); + } + } +#else + long t; + + ret = Jim_GetLong (interp, argv[1], &t); + if (ret == JIM_OK) { + alarm(t); + } +#endif + } + + return ret; +} + +static int Jim_SleepCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int ret; + + if (argc != 2) { + Jim_WrongNumArgs(interp, 1, argv, "seconds"); + return JIM_ERR; + } + else { + double t; + + ret = Jim_GetDouble(interp, argv[1], &t); + if (ret == JIM_OK) { + if (t < 10) { + usleep(t * 1e6); + } + else { + sleep(t); + } + } + } + + return ret; +} + +static int Jim_KillCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv) +{ + int sig; + long pid; + Jim_Obj *pidObj; + const char *signame; + + if (argc != 2 && argc != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?SIG|-0? pid"); + return JIM_ERR; + } + + if (argc == 2) { + signame = "SIGTERM"; + pidObj = argv[1]; + } + else { + signame = Jim_GetString(argv[1], NULL); + pidObj = argv[2]; + } + + /* Special 'kill -0 pid' to determine if a pid exists */ + if (strcmp(signame, "-0") == 0 || strcmp(signame, "0") == 0) { + sig = 0; + } + else { + sig = find_signal_by_name(interp, signame); + if (sig < 0) { + return JIM_ERR; + } + } + + if (Jim_GetLong(interp, pidObj, &pid) != JIM_OK) { + return JIM_ERR; + } + + if (kill(pid, sig) == 0) { + return JIM_OK; + } + + Jim_SetResultString(interp, "kill: Failed to deliver signal", -1); + return JIM_ERR; +} + +int Jim_signalInit(Jim_Interp *interp) +{ + if (Jim_PackageProvide(interp, "signal", "1.0", JIM_ERRMSG) != JIM_OK) { + return JIM_ERR; + } + /* Teach the jim core how to convert signal values to names */ + interp->signal_to_name = Jim_SignalId; + + Jim_CreateCommand(interp, "signal", Jim_SubCmdProc, (void *)signal_command_table, NULL); + Jim_CreateCommand(interp, "alarm", Jim_AlarmCmd, 0, 0); + Jim_CreateCommand(interp, "kill", Jim_KillCmd, 0, 0); + + /* Sleep is slightly dubious here */ + Jim_CreateCommand(interp, "sleep", Jim_SleepCmd, 0, 0); + return JIM_OK; +} @@ -113,33 +113,6 @@ static Jim_HashTableType JimVariablesHashTableType; * Utility functions * ---------------------------------------------------------------------------*/ -static char * -jim_vasprintf( const char *fmt, va_list ap ) -{ -#ifndef HAVE_VASPRINTF - /* yucky way */ -static char buf[2048]; - vsnprintf( buf, sizeof(buf), fmt, ap ); - /* garentee termination */ - buf[sizeof(buf)-1] = 0; -#else - char *buf; - vasprintf( &buf, fmt, ap ); -#endif - return buf; -} - -static void -jim_vasprintf_done( void *buf ) -{ -#ifndef HAVE_VASPRINTF - (void)(buf); -#else - free(buf); -#endif -} - - /* * Convert a string to a jim_wide INTEGER. * This function originates from BSD. @@ -515,9 +488,9 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...) va_list ap; va_start(ap, fmt); - /* - * Send it here first.. Assuming STDIO still works - */ + /* + * Send it here first.. Assuming STDIO still works + */ fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); vfprintf(stderr, fmt, ap); fprintf(stderr, JIM_NL JIM_NL); @@ -538,10 +511,6 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...) } #endif - fprintf(stderr, JIM_NL "JIM INTERPRETER PANIC: "); - vfprintf(stderr, fmt, ap ); - fprintf(stderr, JIM_NL JIM_NL ); - abort(); } @@ -560,9 +529,10 @@ void Jim_Panic(Jim_Interp *interp, const char *fmt, ...) void *Jim_Alloc(int size) { - /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */ - if (size==0) - size=1; + /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */ + if (size==0) { + size = 1; + } void *p = malloc(size); if (p == NULL) Jim_Panic(NULL,"malloc: Out of memory"); @@ -575,9 +545,10 @@ void Jim_Free(void *ptr) { void *Jim_Realloc(void *ptr, int size) { - /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */ - if (size==0) - size=1; + /* We allocate zero length arrayes, etc. to use a single orthogonal codepath */ + if (size==0) { + size = 1; + } void *p = realloc(ptr, size); if (p == NULL) Jim_Panic(NULL,"realloc: Out of memory"); @@ -990,6 +961,7 @@ static void JimStringKeyValCopyHTValDestructor(void *privdata, void *val) Jim_Free((void*)val); /* ATTENTION: const cast */ } +#if 0 static Jim_HashTableType JimStringCopyHashTableType = { JimStringCopyHTHashFunction, /* hash function */ JimStringCopyHTKeyDup, /* key dup */ @@ -998,6 +970,7 @@ static Jim_HashTableType JimStringCopyHashTableType = { JimStringCopyHTKeyDestructor, /* key destructor */ NULL /* val destructor */ }; +#endif /* This is like StringCopy but does not auto-duplicate the key. * It's used for intepreter's shared strings. */ @@ -2048,22 +2021,6 @@ void Jim_AppendString(Jim_Interp *interp, Jim_Obj *objPtr, const char *str, StringAppendString(objPtr, str, len); } -void Jim_AppendString_sprintf( Jim_Interp *interp, Jim_Obj *objPtr, const char *fmt, ... ) -{ - char *buf; - va_list ap; - - va_start( ap, fmt ); - buf = jim_vasprintf( fmt, ap ); - va_end(ap); - - if( buf ){ - Jim_AppendString( interp, objPtr, buf, -1 ); - jim_vasprintf_done(buf); - } -} - - void Jim_AppendObj(Jim_Interp *interp, Jim_Obj *objPtr, Jim_Obj *appendObjPtr) { @@ -2309,27 +2266,26 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr, Jim_Obj *resObjPtr; - fmt = Jim_GetString(fmtObjPtr, &fmtLen); - _fmt = fmt; + _fmt = fmt = Jim_GetString(fmtObjPtr, &fmtLen); resObjPtr = Jim_NewStringObj(interp, "", 0); while (fmtLen) { const char *p = fmt; char spec[2], c; jim_wide wideValue; - double doubleValue; - /* we cheat and use Sprintf()! */ - char fmt_str[100]; - char *cp; - int width; - int ljust; - int zpad; - int spad; - int altfm; - int forceplus; - int prec; - int inprec; - int haveprec; - int accum; + double doubleValue; + /* we cheat and use Sprintf()! */ + char fmt_str[100]; + char *cp; + int width; + int ljust; + int zpad; + int spad; + int altfm; + int forceplus; + int prec; + int inprec; + int haveprec; + int accum; while (*fmt != '%' && fmtLen) { fmt++; fmtLen--; @@ -2338,226 +2294,225 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr, if (fmtLen == 0) break; fmt++; fmtLen--; /* skip '%' */ - zpad = 0; - spad = 0; - width = -1; - ljust = 0; - altfm = 0; - forceplus = 0; - inprec = 0; - haveprec = 0; - prec = -1; /* not found yet */ + zpad = 0; + spad = 0; + width = -1; + ljust = 0; + altfm = 0; + forceplus = 0; + inprec = 0; + haveprec = 0; + prec = -1; /* not found yet */ next_fmt: - if( fmtLen <= 0 ){ - break; - } - switch( *fmt ){ - /* terminals */ + if( fmtLen <= 0 ){ + break; + } + switch( *fmt ){ + /* terminals */ case 'b': /* binary - not all printfs() do this */ - case 's': /* string */ - case 'i': /* integer */ - case 'd': /* decimal */ - case 'x': /* hex */ - case 'X': /* CAP hex */ - case 'c': /* char */ - case 'o': /* octal */ - case 'u': /* unsigned */ - case 'f': /* float */ - break; - - /* non-terminals */ - case '0': /* zero pad */ - zpad = 1; - fmt++; fmtLen--; - goto next_fmt; - break; - case '+': - forceplus = 1; - fmt++; fmtLen--; - goto next_fmt; - break; - case ' ': /* sign space */ - spad = 1; - fmt++; fmtLen--; - goto next_fmt; - break; - case '-': - ljust = 1; - fmt++; fmtLen--; - goto next_fmt; - break; - case '#': - altfm = 1; - fmt++; fmtLen--; - goto next_fmt; - - case '.': - inprec = 1; - fmt++; fmtLen--; - goto next_fmt; - break; - case '1': - case '2': - case '3': - case '4': - case '5': - case '6': - case '7': - case '8': - case '9': - accum = 0; - while( isdigit(*fmt) && (fmtLen > 0) ){ - accum = (accum * 10) + (*fmt - '0'); - fmt++; fmtLen--; - } - if( inprec ){ - haveprec = 1; - prec = accum; - } else { - width = accum; - } - goto next_fmt; - case '*': - /* suck up the next item as an integer */ - fmt++; fmtLen--; - objc--; - if( objc <= 0 ){ - goto not_enough_args; - } - if( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){ - Jim_FreeNewObj(interp, resObjPtr ); - return NULL; - } - if( inprec ){ - haveprec = 1; - prec = wideValue; - if( prec < 0 ){ - /* man 3 printf says */ - /* if prec is negative, it is zero */ - prec = 0; - } - } else { - width = wideValue; - if( width < 0 ){ - ljust = 1; - width = -width; - } - } - objv++; - goto next_fmt; - break; - } - - - if (*fmt != '%') { + case 's': /* string */ + case 'i': /* integer */ + case 'd': /* decimal */ + case 'x': /* hex */ + case 'X': /* CAP hex */ + case 'c': /* char */ + case 'o': /* octal */ + case 'u': /* unsigned */ + case 'f': /* float */ + break; + + /* non-terminals */ + case '0': /* zero pad */ + zpad = 1; + fmt++; fmtLen--; + goto next_fmt; + break; + case '+': + forceplus = 1; + fmt++; fmtLen--; + goto next_fmt; + break; + case ' ': /* sign space */ + spad = 1; + fmt++; fmtLen--; + goto next_fmt; + break; + case '-': + ljust = 1; + fmt++; fmtLen--; + goto next_fmt; + break; + case '#': + altfm = 1; + fmt++; fmtLen--; + goto next_fmt; + + case '.': + inprec = 1; + fmt++; fmtLen--; + goto next_fmt; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + case '9': + accum = 0; + while( isdigit(*fmt) && (fmtLen > 0) ){ + accum = (accum * 10) + (*fmt - '0'); + fmt++; fmtLen--; + } + if( inprec ){ + haveprec = 1; + prec = accum; + } else { + width = accum; + } + goto next_fmt; + case '*': + /* suck up the next item as an integer */ + fmt++; fmtLen--; + objc--; + if( objc <= 0 ){ + goto not_enough_args; + } + if( Jim_GetWide(interp,objv[0],&wideValue )== JIM_ERR ){ + Jim_FreeNewObj(interp, resObjPtr ); + return NULL; + } + if( inprec ){ + haveprec = 1; + prec = wideValue; + if( prec < 0 ){ + /* man 3 printf says */ + /* if prec is negative, it is zero */ + prec = 0; + } + } else { + width = wideValue; + if( width < 0 ){ + ljust = 1; + width = -width; + } + } + objv++; + goto next_fmt; + break; + } + + + if (*fmt != '%') { if (objc == 0) { - not_enough_args: + not_enough_args: Jim_FreeNewObj(interp, resObjPtr); - Jim_SetResultString(interp, - "not enough arguments for all format specifiers", -1); + Jim_SetResultString(interp, "not enough arguments for all format specifiers", -1); return NULL; } else { objc--; } } - - /* - * Create the formatter - * cause we cheat and use sprintf() - */ - cp = fmt_str; - *cp++ = '%'; - if( altfm ){ - *cp++ = '#'; - } - if( forceplus ){ - *cp++ = '+'; - } else if( spad ){ - /* PLUS overrides */ - *cp++ = ' '; - } - if( ljust ){ - *cp++ = '-'; - } - if( zpad ){ - *cp++ = '0'; - } - if( width > 0 ){ - sprintf( cp, "%d", width ); - /* skip ahead */ - cp = strchr(cp,0); - } - /* did we find a period? */ - if( inprec ){ - /* then add it */ - *cp++ = '.'; - /* did something occur after the period? */ - if( haveprec ){ - sprintf( cp, "%d", prec ); - } - cp = strchr(cp,0); - } - *cp = 0; - - /* here we do the work */ - /* actually - we make sprintf() do it for us */ + + /* + * Create the formatter + * cause we cheat and use sprintf() + */ + cp = fmt_str; + *cp++ = '%'; + if( altfm ){ + *cp++ = '#'; + } + if( forceplus ){ + *cp++ = '+'; + } else if( spad ){ + /* PLUS overrides */ + *cp++ = ' '; + } + if( ljust ){ + *cp++ = '-'; + } + if( zpad ){ + *cp++ = '0'; + } + if( width > 0 ){ + sprintf( cp, "%d", width ); + /* skip ahead */ + cp = strchr(cp,0); + } + /* did we find a period? */ + if( inprec ){ + /* then add it */ + *cp++ = '.'; + /* did something occur after the period? */ + if( haveprec ){ + sprintf( cp, "%d", prec ); + } + cp = strchr(cp,0); + } + *cp = 0; + + /* here we do the work */ + /* actually - we make sprintf() do it for us */ switch(*fmt) { case 's': - *cp++ = 's'; - *cp = 0; - /* BUG: we do not handled embeded NULLs */ - snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, Jim_GetString( objv[0], NULL )); + *cp++ = 's'; + *cp = 0; + /* BUG: we do not handled embeded NULLs */ + snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, Jim_GetString( objv[0], NULL )); break; case 'c': - *cp++ = 'c'; - *cp = 0; + *cp++ = 'c'; + *cp = 0; if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) { Jim_FreeNewObj(interp, resObjPtr); return NULL; } c = (char) wideValue; - snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, c ); + snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, c ); + break; + case 'f': + case 'F': + case 'g': + case 'G': + case 'e': + case 'E': + *cp++ = *fmt; + *cp = 0; + if( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){ + Jim_FreeNewObj( interp, resObjPtr ); + return NULL; + } + snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, doubleValue ); break; - case 'f': - case 'F': - case 'g': - case 'G': - case 'e': - case 'E': - *cp++ = *fmt; - *cp = 0; - if( Jim_GetDouble( interp, objv[0], &doubleValue ) == JIM_ERR ){ - Jim_FreeNewObj( interp, resObjPtr ); - return NULL; - } - snprintf( sprintf_buf, JIM_MAX_FMT, fmt_str, doubleValue ); - break; case 'b': case 'd': case 'o': - case 'i': - case 'u': - case 'x': - case 'X': - /* jim widevaluse are 64bit */ - if( sizeof(jim_wide) == sizeof(long long) ){ - *cp++ = 'l'; - *cp++ = 'l'; - } else { - *cp++ = 'l'; - } - *cp++ = *fmt; - *cp = 0; + case 'i': + case 'u': + case 'x': + case 'X': + /* jim widevaluse are 64bit */ + if( sizeof(jim_wide) == sizeof(long long) ){ + *cp++ = 'l'; + *cp++ = 'l'; + } else { + *cp++ = 'l'; + } + *cp++ = *fmt; + *cp = 0; if (Jim_GetWide(interp, objv[0], &wideValue) == JIM_ERR) { Jim_FreeNewObj(interp, resObjPtr); return NULL; } - snprintf(sprintf_buf, JIM_MAX_FMT, fmt_str, wideValue ); + snprintf(sprintf_buf, JIM_MAX_FMT, fmt_str, wideValue ); break; case '%': - sprintf_buf[0] = '%'; - sprintf_buf[1] = 0; - objv--; /* undo the objv++ below */ + sprintf_buf[0] = '%'; + sprintf_buf[1] = 0; + objv--; /* undo the objv++ below */ break; default: spec[0] = *fmt; spec[1] = '\0'; @@ -2567,16 +2522,16 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr, "bad field specifier \"", spec, "\"", NULL); return NULL; } - /* force terminate */ + /* force terminate */ #if 0 - printf("FMT was: %s\n", fmt_str ); - printf("RES was: |%s|\n", sprintf_buf ); + printf("FMT was: %s\n", fmt_str ); + printf("RES was: |%s|\n", sprintf_buf ); #endif - - sprintf_buf[ JIM_MAX_FMT - 1] = 0; - Jim_AppendString( interp, resObjPtr, sprintf_buf, strlen(sprintf_buf) ); - /* next obj */ - objv++; + + sprintf_buf[ JIM_MAX_FMT - 1] = 0; + Jim_AppendString( interp, resObjPtr, sprintf_buf, strlen(sprintf_buf) ); + /* next obj */ + objv++; fmt++; fmtLen--; } @@ -2586,10 +2541,10 @@ static Jim_Obj *Jim_FormatString_Inner(Jim_Interp *interp, Jim_Obj *fmtObjPtr, Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_Obj *const *objv) { - char *sprintf_buf=malloc(JIM_MAX_FMT); - Jim_Obj *t=Jim_FormatString_Inner(interp, fmtObjPtr, objc, objv, sprintf_buf); - free(sprintf_buf); - return t; + char *sprintf_buf=malloc(JIM_MAX_FMT); + Jim_Obj *t=Jim_FormatString_Inner(interp, fmtObjPtr, objc, objv, sprintf_buf); + free(sprintf_buf); + return t; } /* ----------------------------------------------------------------------------- @@ -4432,7 +4387,6 @@ Jim_Interp *Jim_CreateInterp(void) Jim_InitHashTable(&i->references, &JimReferencesHashTableType, i); Jim_InitHashTable(&i->sharedStrings, &JimSharedStringsHashTableType, NULL); - Jim_InitHashTable(&i->stub, &JimStringCopyHashTableType, NULL); Jim_InitHashTable(&i->assocData, &JimAssocDataHashTableType, i); Jim_InitHashTable(&i->packages, &JimStringKeyValCopyHashTableType, NULL); i->framePtr = i->topFramePtr = JimCreateCallFrame(i); @@ -4476,7 +4430,6 @@ void Jim_FreeInterp(Jim_Interp *i) Jim_Free((void*)i->scriptFileName); Jim_FreeHashTable(&i->commands); Jim_FreeHashTable(&i->references); - Jim_FreeHashTable(&i->stub); Jim_FreeHashTable(&i->assocData); Jim_FreeHashTable(&i->packages); Jim_Free(i->prngState); @@ -5274,8 +5227,6 @@ static int ListSortCommand(Jim_Obj **lhsObj, Jim_Obj **rhsObj) Jim_Obj *compare_script = Jim_DuplicateObj(sort_interp, sort_command); long ret = 0; - //fprintf(stderr, "ListSortCommand: lhsObj=%s, rhsObj=%s\n", Jim_GetString(*lhsObj, NULL), Jim_GetString(*rhsObj, NULL)); - /* We have already had an error, so just compare pointers */ if (sort_result != JIM_OK) { return (long)lhsObj - (long)rhsObj; @@ -6378,7 +6329,7 @@ int JimParseExprNumber(struct JimParserCtx *pc) if ((*pc->p == 'x') || (*pc->p == 'X')) { allowhex = 1; allowdot = 0; - } + } if (*pc->p == '.') allowdot = 0; pc->p++; pc->len--; @@ -7978,6 +7929,7 @@ int Jim_EvalObjVector(Jim_Interp *interp, int objc, Jim_Obj *const *objv) /* Decr refcount of arguments and return the retcode */ for (i = 0; i < objc; i++) Jim_DecrRefCount(interp, objv[i]); + return retcode; } @@ -8199,8 +8151,9 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) break; case JIM_TT_CMD: retcode = Jim_EvalObj(interp, token[i].objPtr); - if (retcode != JIM_OK) + if (retcode != JIM_OK) { goto err; + } argv[j] = Jim_GetResult(interp); break; default: @@ -8274,6 +8227,10 @@ int Jim_EvalObj(Jim_Interp *interp, Jim_Obj *scriptObjPtr) token[i-argc*2].linenr); } } + if (interp->signal_level && interp->signal) { + /* Check for a signal after each command */ + retcode = JIM_SIGNAL; + } if (retcode != JIM_OK) { i -= argc*2; /* point to the command name. */ goto err; @@ -8437,13 +8394,13 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename, int retval; Jim_Obj *scriptObjPtr; - scriptObjPtr = Jim_NewStringObj(interp, script, -1); + scriptObjPtr = Jim_NewStringObj(interp, script, -1); Jim_IncrRefCount(scriptObjPtr); - if( filename ){ - JimSetSourceInfo( interp, scriptObjPtr, filename, lineno ); - } + if( filename ){ + JimSetSourceInfo( interp, scriptObjPtr, filename, lineno ); + } retval = Jim_EvalObj(interp, scriptObjPtr); Jim_DecrRefCount(interp, scriptObjPtr); @@ -8452,7 +8409,7 @@ int Jim_Eval_Named(Jim_Interp *interp, const char *script, const char *filename, int Jim_Eval(Jim_Interp *interp, const char *script) { - return Jim_Eval_Named( interp, script, NULL, 0 ); + return Jim_Eval_Named( interp, script, NULL, 0 ); } @@ -8498,6 +8455,7 @@ int Jim_EvalObjBackground(Jim_Interp *interp, Jim_Obj *scriptObjPtr) return retval; } +/* REVISIT: Just load the file with a single malloc/fread then Jim_EvalObj() */ int Jim_EvalFile(Jim_Interp *interp, const char *filename) { char *prg = NULL; @@ -8507,15 +8465,15 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) Jim_Obj *scriptObjPtr; if ((fp = fopen(filename, "r")) == NULL) { - const int cwd_len=2048; - char *cwd=malloc(cwd_len); + const int cwd_len=2048; + char *cwd=malloc(cwd_len); Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - getcwd( cwd, cwd_len ); + getcwd( cwd, cwd_len ); Jim_AppendStrings(interp, Jim_GetResult(interp), - "Error loading script \"", filename, "\"", - " cwd: ", cwd, - " err: ", strerror(errno), NULL); - free(cwd); + "Error loading script \"", filename, "\"", + " cwd: ", cwd, + " err: ", strerror(errno), NULL); + free(cwd); return JIM_ERR; } buflen = 1024; @@ -8525,12 +8483,10 @@ int Jim_EvalFile(Jim_Interp *interp, const char *filename) maxlen = totread+buflen+1; prg = Jim_Realloc(prg, maxlen); } - /* do not use Jim_fread() - this is really a file */ if ((nread = fread(prg+totread, 1, buflen, fp)) == 0) break; totread += nread; } prg[totread] = '\0'; - /* do not use Jim_fclose() - this is really a file */ fclose(fp); scriptObjPtr = Jim_NewStringObjNoAlloc(interp, prg, totread); @@ -9682,8 +9638,8 @@ static int Jim_IfCoreCommand(Jim_Interp *interp, int argc, return Jim_EvalObj(interp, argv[current]); /* Ok: no else-clause follows */ if (++current >= argc) { - Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); - return JIM_OK; + Jim_SetResult(interp, Jim_NewEmptyStringObj(interp)); + return JIM_OK; } falsebody = current++; if (Jim_CompareStringImmediate(interp, argv[falsebody], @@ -10795,12 +10751,44 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) { int exitCode = 0; + int sig = 0; - if (argc != 2 && argc != 3) { - Jim_WrongNumArgs(interp, 1, argv, "script ?varName?"); + if (argc > 1 && Jim_CompareStringImmediate(interp, argv[1], "-signal")) { + sig++; + } + + if (argc - sig != 2 && argc - sig != 3) { + Jim_WrongNumArgs(interp, 1, argv, "?-signal? script ?varName?"); return JIM_ERR; } + argc -= sig; + argv += sig; + + interp->signal_level += sig; exitCode = Jim_EvalObj(interp, argv[1]); + interp->signal_level -= sig; + + + /* If we get TCL_SIGNAL without the -signal parameter, + * just pass it through to be caught at a higher level + */ + if (exitCode == JIM_SIGNAL && !sig) { + return exitCode; + } + + if (sig) { + if (exitCode == JIM_SIGNAL && interp->signal_level == 0) { + /* Yes, catch the signal at this level */ + if (interp->signal_to_name) { + Jim_SetResultString(interp, interp->signal_to_name(interp->signal), -1); + } + else { + Jim_SetResultInt(interp, interp->signal); + } + interp->signal = 0; + } + } + if (argc == 3) { if (Jim_SetVariable(interp, argv[2], Jim_GetResult(interp)) != JIM_OK) @@ -10996,17 +10984,6 @@ static int Jim_DictCoreCommand(Jim_Interp *interp, int argc, return JIM_OK; } -/* [load] */ -static int Jim_LoadCoreCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - if (argc < 2) { - Jim_WrongNumArgs(interp, 1, argv, "libaryFile"); - return JIM_ERR; - } - return Jim_LoadLibrary(interp, Jim_GetString(argv[1], NULL)); -} - /* [subst] */ static int Jim_SubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv) @@ -11536,54 +11513,6 @@ static int Jim_RandCoreCommand(Jim_Interp *interp, int argc, } } -/* [package] */ -static int Jim_PackageCoreCommand(Jim_Interp *interp, int argc, - Jim_Obj *const *argv) -{ - int option; - const char *options[] = { - "require", "provide", NULL - }; - enum {OPT_REQUIRE, OPT_PROVIDE}; - - if (argc < 2) { - Jim_WrongNumArgs(interp, 1, argv, "option ?arguments ...?"); - return JIM_ERR; - } - if (Jim_GetEnum(interp, argv[1], options, &option, "option", - JIM_ERRMSG) != JIM_OK) - return JIM_ERR; - - if (option == OPT_REQUIRE) { - int exact = 0; - const char *ver; - - if (Jim_CompareStringImmediate(interp, argv[2], "-exact")) { - exact = 1; - argv++; - argc--; - } - if (argc != 3 && argc != 4) { - Jim_WrongNumArgs(interp, 2, argv, "?-exact? package ?version?"); - return JIM_ERR; - } - ver = Jim_PackageRequire(interp, Jim_GetString(argv[2], NULL), - argc == 4 ? Jim_GetString(argv[3], NULL) : "", - JIM_ERRMSG); - if (ver == NULL) - return JIM_ERR_ADDSTACK; - Jim_SetResultString(interp, ver, -1); - } else if (option == OPT_PROVIDE) { - if (argc != 4) { - Jim_WrongNumArgs(interp, 2, argv, "package version"); - return JIM_ERR; - } - return Jim_PackageProvide(interp, Jim_GetString(argv[2], NULL), - Jim_GetString(argv[3], NULL), JIM_ERRMSG); - } - return JIM_OK; -} - static struct { const char *name; Jim_CmdProc cmdProc; @@ -11632,7 +11561,6 @@ static struct { {"collect", Jim_CollectCoreCommand}, {"rename", Jim_RenameCoreCommand}, {"dict", Jim_DictCoreCommand}, - {"load", Jim_LoadCoreCommand}, {"subst", Jim_SubstCoreCommand}, {"info", Jim_InfoCoreCommand}, {"split", Jim_SplitCoreCommand}, @@ -11646,7 +11574,6 @@ static struct { {"lreverse", Jim_LreverseCoreCommand}, {"range", Jim_RangeCoreCommand}, {"rand", Jim_RandCoreCommand}, - {"package", Jim_PackageCoreCommand}, {"tailcall", Jim_TailcallCoreCommand}, {NULL, NULL}, }; @@ -141,9 +141,10 @@ extern "C" { #define JIM_RETURN 2 #define JIM_BREAK 3 #define JIM_CONTINUE 4 -#define JIM_EVAL 5 -#define JIM_EXIT 6 -#define JIM_ERR_ADDSTACK 7 +#define JIM_SIGNAL 5 +#define JIM_EVAL 6 +#define JIM_EXIT 7 +#define JIM_ERR_ADDSTACK 8 #define JIM_MAX_NESTING_DEPTH 10000 /* default max nesting depth */ /* Some function get an integer argument with flags to change @@ -477,6 +478,10 @@ typedef struct Jim_Interp { int maxNestingDepth; /* Used for infinite loop detection. */ int returnCode; /* Completion code to return on JIM_RETURN. */ int exitCode; /* Code to return to the OS on JIM_EXIT. */ + int signal; /* A caught signal, or 0 if none */ + int signal_level; /* A nesting level of catch -signal */ + long id; /* Hold unique id for various purposes */ + const char *(*signal_to_name)(int sig); /* Returns a name for the signal number */ Jim_CallFrame *framePtr; /* Pointer to the current call frame */ Jim_CallFrame *topFramePtr; /* toplevel/global frame pointer. */ struct Jim_HashTable commands; /* Commands hash table */ @@ -510,9 +515,6 @@ typedef struct Jim_Interp { a command. It is set to what the user specified via Jim_CreateCommand(). */ - struct Jim_HashTable stub; /* Stub hash table to export API */ - /* Jim_GetApi() function pointer, used to bootstrap the STUB table */ - int (*getApiFuncPtr)(struct Jim_Interp *, const char *, void *); struct Jim_CallFrame *freeFramesList; /* list of CallFrame structures. */ struct Jim_HashTable assocData; /* per-interp storage for use by packages */ Jim_PrngState *prngState; /* per interpreter Random Number Gen. state. */ @@ -539,6 +541,9 @@ typedef struct Jim_Interp { (i)->result = _resultObjPtr_; \ } while(0) +/* Use this for filehandles, etc. which need a unique id */ +#define Jim_GetId(i) (++(i)->id) + /* Reference structure. The interpreter pointer is held within privdata member in HashTable */ #define JIM_REFERENCE_TAGLEN 7 /* The tag is fixed-length, because the reference string representation must be fixed length. */ @@ -824,6 +829,10 @@ int Jim_StringToWide(const char *str, jim_wide *widePtr, int base); /* jim-load.c */ int Jim_LoadLibrary(Jim_Interp *interp, const char *pathName); + +/* jim-aio.c */ +FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command); + #ifdef __cplusplus } #endif |