#else
#define _GNU_SOURCE
#endif
+#ifndef __ixemul__
#define HAVE_FORK
+#else
+#define HAVE_VFORK
+#endif
#define HAVE_WAITPID
#define HAVE_ISATTY
#define HAVE_MKSTEMP
-#define JIM_ABI_VERSION 101
+#define JIM_ABI_VERSION 102
+
#define JIM_OK 0
#define JIM_ERR 1
#define JIM_SIGNAL 5
#define JIM_EXIT 6
+#define JIM_USAGE -1
+
#define JIM_EVAL 7
#define JIM_MAX_CALLFRAME_DEPTH 1000
#define JIM_NONE 0
#define JIM_ERRMSG 1
-#define JIM_ENUM_ABBREV 2
#define JIM_UNSHARED 4
#define JIM_MUSTEXIST 8
#define JIM_NORESULT 16
#define JIM_SUBST_NOESC 4
#define JIM_SUBST_FLAG 128
+#define JIM_TAINT_STD 1 /* The "normal" type of taint. Allows for multiple
+ * types of taint in the future
+ */
+#define JIM_TAINT_ANY ~0
+
+
+#define JIM_ENUM_ABBREV 2
+
#define JIM_CASESENS 0
#define JIM_NOCASE 1
int len;
int maxlen;
void **vector;
+ void (*freefunc) (void *ptr);
} Jim_Stack;
const struct Jim_ObjType *typePtr;
int refCount;
int length;
+ unsigned taint;
union {
Jim_Obj *procBodyObjPtr;
struct Jim_CallFrame *next;
Jim_Obj *nsObj;
- Jim_Obj *unused_fileNameObj;
- int unused_line;
Jim_Stack *localCommands;
struct Jim_Obj *tailcallObj;
struct Jim_Cmd *tailcallCmd;
unsigned int dummy;
} Jim_Dict;
+#define JIM_CMD_ISPROC 1
+#define JIM_CMD_ISCHANNEL 2
+#define JIM_CMD_ISALIAS 4
+
+#define JIM_CMD_NOTAINT 0x100
+
typedef struct Jim_Cmd {
int inUse;
- int isproc;
+ int flags;
struct Jim_Cmd *prevCmd;
Jim_Obj *cmdNameObj;
union {
Jim_CmdProc *cmdProc;
Jim_DelCmdProc *delProc;
void *privData;
+ const char *usage;
+ const char *help;
+ short minargs;
+ short maxargs;
} native;
struct {
typedef struct Jim_Interp {
Jim_Obj *result;
- int unused_errorLine;
Jim_Obj *currentFilenameObj;
int break_level;
int maxCallFrameDepth;
int safeexpr;
Jim_Obj *liveList;
Jim_Obj *freeList;
- Jim_Obj *unused_currentScriptObj;
Jim_EvalFrame topEvalFrame;
Jim_EvalFrame *evalFrame;
int procLevel;
- Jim_Obj * const *unused_argv;
Jim_Obj *nullScriptObj;
Jim_Obj *emptyObj;
Jim_Obj *trueObj;
Jim_Obj *defer;
Jim_Obj *traceCmdObj;
int unknown_called;
- int errorFlag;
+ int hasErrorStackTrace;
void *cmdPrivData; /* Used to pass the private data pointer to
a command. It is set to what the user specified
via Jim_CreateCommand(). */
Jim_PrngState *prngState;
struct Jim_HashTable packages;
Jim_Stack *loadHandles;
+ unsigned taint;
} Jim_Interp;
#define Jim_SetResultString(i,s,l) Jim_SetResult(i, Jim_NewStringObj(i,s,l))
-JIM_EXPORT void Jim_InitStack(Jim_Stack *stack);
-JIM_EXPORT void Jim_FreeStack(Jim_Stack *stack);
-JIM_EXPORT int Jim_StackLen(Jim_Stack *stack);
+JIM_EXPORT void Jim_StackInit(Jim_Stack *stack, void (*freefunc) (void *ptr));
+JIM_EXPORT void Jim_StackFree(Jim_Stack *stack);
JIM_EXPORT void Jim_StackPush(Jim_Stack *stack, void *element);
-JIM_EXPORT void * Jim_StackPop(Jim_Stack *stack);
-JIM_EXPORT void * Jim_StackPeek(Jim_Stack *stack);
-JIM_EXPORT void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc)(void *ptr));
+JIM_EXPORT void *Jim_StackPop(Jim_Stack *stack);
JIM_EXPORT int Jim_InitHashTable (Jim_HashTable *ht,
JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, ...);
-JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp);
+JIM_EXPORT Jim_Cmd *Jim_RegisterCommand(Jim_Interp *interp, Jim_Obj *cmdNameObj,
+ Jim_CmdProc *cmdProc,
+ Jim_DelCmdProc *delProc,
+ const char *usage,
+ const char *help,
+ short minargs,
+ short maxargs,
+ int flags,
+ void *privData);
+
JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp,
const char *cmdName, Jim_CmdProc *cmdProc, void *privData,
Jim_DelCmdProc *delProc);
+#define Jim_RegisterSimpleCmd(interp, name, usage, minargs, maxargs, cmdproc) \
+ Jim_RegisterCommand(interp, Jim_NewStringObj(interp, name, -1), cmdproc, NULL, usage, NULL, minargs, maxargs, 0, NULL)
+
+#define Jim_RegisterCmd(interp, name, usage, minargs, maxargs, cmdproc, delproc, privdata, flags) \
+ Jim_RegisterCommand(interp, Jim_NewStringObj(interp, name, -1), cmdproc, delproc, usage, NULL, minargs, maxargs, flags, privdata)
+
+JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp);
JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp,
Jim_Obj *cmdNameObj);
JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
Jim_Obj *oldNameObj, Jim_Obj *newNameObj);
JIM_EXPORT Jim_Cmd * Jim_GetCommand (Jim_Interp *interp,
Jim_Obj *objPtr, int flags);
+
JIM_EXPORT int Jim_SetVariable (Jim_Interp *interp,
Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr);
JIM_EXPORT int Jim_SetVariableStr (Jim_Interp *interp,
JIM_EXPORT int Jim_IsDict(Jim_Obj *objPtr);
JIM_EXPORT int Jim_IsList(Jim_Obj *objPtr);
+
+JIM_EXPORT void Jim_SetTaintError(Jim_Interp *interp, int cmdargs, Jim_Obj *const *argv);
+JIM_EXPORT int Jim_CalcTaint(int argc, Jim_Obj *const *argv);
+
+#ifdef JIM_TAINT
+#define Jim_CheckTaint(i, t) ((i)->taint & (t))
+#define Jim_TaintObj(o,t) (o)->taint |= (t)
+#define Jim_UntaintObj(o) (o)->taint = 0
+#define Jim_GetObjTaint(o) (o)->taint
+#else
+#define Jim_CheckTaint(i, t) 0
+#define Jim_TaintObj(o,t)
+#define Jim_UntaintObj(o)
+#define Jim_GetObjTaint(o) 0
+#endif
+
#ifdef __cplusplus
}
#endif
#define JIM_MODFLAG_HIDDEN 0x0001
#define JIM_MODFLAG_FULLARGV 0x0002
+#define JIM_MODFLAG_NOTAINT 0x0004
+
+#define JIM_SUBCMD_BADARGS -1
+#define JIM_SUBCMD_TAINTED -2
void Jim_SubCmdArgError(Jim_Interp *interp, const jim_subcmd_type *ct, Jim_Obj *subcmd);
+Jim_Cmd *Jim_RegisterSubCmd(Jim_Interp *interp, const char *cmdname,
+ const jim_subcmd_type *command_table, Jim_DelCmdProc *delProc);
+
#ifdef __cplusplus
}
#endif
int regmust;
int regmlen;
int *program;
+ char *exp;
const char *regparse;
typedef regexp regex_t;
#define REG_EXTENDED 0
-#define REG_NEWLINE 1
#define REG_ICASE 2
+#define REG_NEWLINE_ANCHOR 4
+#define REG_NEWLINE_STOP 8
+
+#define REG_NEWLINE (REG_NEWLINE_ANCHOR | REG_NEWLINE_STOP)
#define REG_NOTBOL 16
+#define REG_EXPANDED 32
enum {
REG_NOERROR,
"\n"
"proc tcl::stdhint {string} {\n"
" set result \"\"\n"
+" lassign $string cmd arg\n"
" if {[llength $string] >= 2} {\n"
-" lassign $string cmd arg\n"
" if {$cmd in $::tcl::stdhint_commands || [info channel $cmd] ne \"\"} {\n"
" catch {\n"
" set help [$cmd -help $arg]\n"
" }\n"
" }\n"
" }\n"
+" } else {\n"
+" catch {\n"
+" if {[exists -alias $cmd] && [llength [info alias $cmd]] == 1} {\n"
+"\n"
+"\n"
+"\n"
+" set help [info usage [info alias $cmd]]\n"
+" } else {\n"
+" set help [info usage $cmd]\n"
+" }\n"
+" set hint [join [lrange $help 1 end]]\n"
+" set prefix \" \"\n"
+" if {[string match \"* \" $string]} {\n"
+" set prefix \"\"\n"
+" }\n"
+" set result [list $prefix$hint {*}$::tcl::stdhint_col]\n"
+" }\n"
" }\n"
" return $result\n"
"}\n"
"\n"
"\n"
"\n"
-"proc parray {arrayname {pattern *} {puts puts}} {\n"
+"\n"
+"\n"
+"proc parray {arrayname {pattern *} {puts puts} args} {\n"
" upvar $arrayname a\n"
"\n"
" set max 0\n"
" incr max [string length $arrayname]\n"
" incr max 2\n"
" foreach name [lsort [array names a $pattern]] {\n"
-" $puts [format \"%-${max}s = %s\" $arrayname\\($name\\) $a($name)]\n"
+" $puts {*}$args [format \"%-${max}s = %s\" $arrayname\\($name\\) $a($name)]\n"
" }\n"
"}\n"
"\n"
#define AIO_EOF 4
#define AIO_WBUF_NONE 8
#define AIO_NONBLOCK 16
+#define AIO_NOTAINT 32
#define AIO_ONEREAD 32
int (*reader)(struct AioFile *af, char *buf, int len, int pending);
int (*error)(const struct AioFile *af);
const char *(*strerror)(struct AioFile *af);
- int (*verify)(struct AioFile *af);
} JimAioFopsType;
typedef struct AioFile
int flags;
long timeout;
int fd;
+ unsigned taintsource;
+ unsigned taintsink;
int addr_family;
void *ssl;
const JimAioFopsType *fops;
stdio_reader,
stdio_error,
stdio_strerror,
- NULL,
};
}
static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
+static void JimAioSetTaint(AioFile *af, int taintsource, int taintsink);
static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
const char *hdlfmt, int family, int flags);
argv++;
}
if (argc) {
- return -1;
+ return JIM_USAGE;
}
return JIM_ERR;
}
objPtr = aio_read_consume(interp, af, neededLen);
+ Jim_TaintObj(objPtr, af->taintsource);
aio_set_nonblocking(af, nb);
Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
- if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
+ if (cmdPtr && !(cmdPtr->flags & JIM_CMD_ISPROC) && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
return ((AioFile *) cmdPtr->u.native.privData)->fd;
}
Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
return JIM_OK;
}
+static int aio_cmd_gettaint(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ static const char * const options[] = { "-source", "-sink", NULL };
+ enum { OPT_SOURCE, OPT_SINK };
+ int option;
+
+ if (Jim_GetEnum(interp, argv[0], options, &option, NULL, JIM_ERRMSG) != JIM_OK) {
+ return JIM_ERR;
+ }
+ switch (option) {
+ case OPT_SOURCE:
+ Jim_SetResultInt(interp, af->taintsource);
+ break;
+
+ case OPT_SINK:
+ Jim_SetResultInt(interp, af->taintsink);
+ break;
+ }
+
+ return JIM_OK;
+}
+
static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
jim_wide maxlen = JIM_WIDE_MAX;
int ok = 1;
Jim_Obj *objv[4];
+ long taintsink;
if (argc == 2) {
if (Jim_GetWide(interp, argv[1], &maxlen) != JIM_OK) {
}
}
+ objv[0] = argv[0];
+ objv[1] = Jim_NewStringObj(interp, "gettaint", -1);
+ objv[2] = Jim_NewStringObj(interp, "-sink", -1);
+ if (Jim_EvalObjVector(interp, 3, objv) != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &taintsink) != JIM_OK) {
+ Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", argv[0]);
+ return JIM_ERR;
+ }
+
+ if (af->taintsource & taintsink) {
+ Jim_SetResultString(interp, "copying tainted source", -1);
+ return JIM_ERR;
+ }
+
objv[0] = argv[0];
objv[1] = Jim_NewStringObj(interp, "flush", -1);
if (Jim_EvalObjVector(interp, 2, objv) != JIM_OK) {
return JIM_OK;
}
+
+static const char *jim_strstr(const char *haystack, int haylen, const char *needle, int needlen)
+{
+ if (needlen == 1) {
+ return (const char *)memchr(haystack, needle[0], haylen);
+ }
+ return strstr(haystack, needle);
+}
+
static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
int len;
int nb;
unsigned flags = AIO_ONEREAD;
- char *nl = NULL;
+ const char *nl = NULL;
int offset = 0;
+ long keepnl = 0;
+ const char *nlstr = "\n";
+ int nlstrlen = 1;
+
+ while (argc >= 2) {
+ enum {OPT_EOL, OPT_KEEP};
+ static const char * const options[] = {
+ "-eol",
+ "-keep",
+ NULL
+ };
+ int opt;
+
+
+ if (*Jim_String(argv[0]) != '-') {
+ return JIM_USAGE;
+ }
+
+ if (Jim_GetEnum(interp, argv[0], options, &opt, NULL, JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+ return JIM_ERR;
+ }
+
+ switch (opt) {
+ case OPT_EOL:
+ nlstr = Jim_GetString(argv[1], &nlstrlen);
+ break;
+
+ case OPT_KEEP:
+ if (Jim_GetLong(interp, argv[1], &keepnl) != JIM_OK) {
+ return JIM_ERR;
+ }
+ break;
+ }
+ argc -= 2;
+ argv += 2;
+ }
errno = 0;
while (!aio_eof(af)) {
if (af->readbuf) {
const char *pt = Jim_GetString(af->readbuf, &len);
- nl = memchr(pt + offset, '\n', len - offset);
+ nl = jim_strstr(pt + offset, len - offset, nlstr, nlstrlen);
if (nl) {
- objPtr = Jim_NewStringObj(interp, pt, nl - pt);
+ objPtr = Jim_NewStringObj(interp, pt, nl - pt + (keepnl ? nlstrlen : 0));
- aio_consume(af->readbuf, nl - pt + 1);
+ aio_consume(af->readbuf, nl - pt + nlstrlen);
break;
}
offset = len;
else if (!objPtr) {
objPtr = Jim_NewStringObj(interp, NULL, 0);
}
+ Jim_TaintObj(objPtr, af->taintsource);
if (argc) {
if (Jim_SetVariable(interp, argv[0], objPtr) != JIM_OK) {
- Jim_FreeNewObj(interp, objPtr);
return JIM_ERR;
}
int wnow = 0;
int nl = 1;
+ if (Jim_CheckTaint(interp, af->taintsink)) {
+ Jim_SetResultString(interp, "puts: tainted data", -1);
+ return JIM_ERR;
+ }
+
if (argc == 2) {
if (!Jim_CompareStringImmediate(interp, argv[0], "-nonewline")) {
- return -1;
+ return JIM_USAGE;
}
strObj = argv[1];
nl = 0;
else if (Jim_CompareStringImmediate(interp, argv[1], "end"))
orig = SEEK_END;
else {
- return -1;
+ return JIM_USAGE;
}
}
if (Jim_GetWide(interp, argv[0], &offset) != JIM_OK) {
return JIM_OK;
}
+#ifdef JIM_TAINT
+static int aio_cmd_taint(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+ static const char * const types[] = {
+ "sink",
+ "source",
+ NULL
+ };
+ enum
+ {
+ TAINT_TYPE_SINK,
+ TAINT_TYPE_SOURCE,
+ };
+ int type;
+ long taint;
+
+ if (Jim_GetEnum(interp, argv[0], types, &type, NULL, JIM_ERRMSG) != JIM_OK)
+ return JIM_ERR;
+
+ if (argc == 1) {
+ Jim_SetResultInt(interp, type == TAINT_TYPE_SINK ? af->taintsink : af->taintsource);
+ return JIM_OK;
+ }
+ else if (Jim_GetLong(interp, argv[1], &taint) == JIM_OK) {
+ if (type == TAINT_TYPE_SINK) {
+ af->taintsink = taint;
+ }
+ else {
+ af->taintsource = taint;
+ }
+ return JIM_OK;
+ }
+ else {
+ return JIM_ERR;
+ }
+}
+#endif
+
#ifdef O_NDELAY
static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
aio_cmd_getfd,
0,
0,
+ JIM_MODFLAG_HIDDEN,
+
+ },
+ { "gettaint",
+ "?-source|-sink?",
+ aio_cmd_gettaint,
+ 1,
+ 1,
+ JIM_MODFLAG_HIDDEN,
},
{ "gets",
- "?var?",
+ "?-eol <str>? ?-keep 0|1? ?var?",
aio_cmd_gets,
0,
- 1,
+ -1,
},
{ "puts",
0,
},
+#ifdef JIM_TAINT
+ { "taint",
+ "source|sink ?0|n?",
+ aio_cmd_taint,
+ 1,
+ 2,
+
+ },
+#endif
#ifdef O_NDELAY
{ "ndelay",
"?0|1?",
Jim_Obj *const *argv)
{
int openflags;
+ AioFile *af;
const char *filename;
int fd = -1;
int n = 0;
- int flags = 0;
+
+ int flags = AIO_NOTAINT;
if (argc > 2 && Jim_CompareStringImmediate(interp, argv[2], "-noclose")) {
flags = AIO_KEEPOPEN;
n++;
}
- if (argc < 2 || argc > 3 + n) {
- Jim_WrongNumArgs(interp, 1, argv, "filename ?-noclose? ?mode?");
+
+ if (Jim_CheckTaint(interp, JIM_TAINT_ANY)) {
+ Jim_SetTaintError(interp, 1, argv);
return JIM_ERR;
}
+ if (argc > 3 + n) {
+ return JIM_USAGE;
+ }
filename = Jim_String(argv[1]);
else {
openflags = O_RDONLY;
}
+
fd = open(filename, openflags, 0666);
if (fd < 0) {
JimAioSetError(interp, argv[1]);
return JIM_ERR;
}
- return JimMakeChannel(interp, fd, argv[1], "aio.handle%ld", 0, flags) ? JIM_OK : JIM_ERR;
+ af = JimMakeChannel(interp, fd, argv[1], "aio.handle%ld", 0, flags);
+ if (af) {
+
+ JimAioSetTaint(af, 0, 0);
+ return JIM_OK;
+ }
+ return JIM_ERR;
}
+static void JimAioSetTaint(AioFile *af, int taintsource, int taintsink)
+{
+ af->taintsource = taintsource;
+ af->taintsink = taintsink;
+}
+
static AioFile *JimMakeChannel(Jim_Interp *interp, int fd, Jim_Obj *filename,
const char *hdlfmt, int family, int flags)
{
af->rbuf_len = AIO_DEFAULT_RBUF_LEN;
- Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
+
+ if (!(flags & AIO_NOTAINT)) {
+ JimAioSetTaint(af, JIM_TAINT_STD, JIM_TAINT_STD);
+ }
+ Jim_RegisterCommand(interp, cmdname,
+ JimAioSubCmdProc, JimAioDelProc,
+ NULL,
+ NULL,
+ 0, -1, JIM_CMD_ISCHANNEL, af);
Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, cmdname));
static int JimAioPipeCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
- return JIM_ERR;
- }
return JimCreatePipe(interp, argv[0], 0);
}
#endif
int p[2];
char path[MAXPATHLEN];
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
- return JIM_ERR;
- }
-
if (openpty(&p[0], &p[1], path, NULL, NULL) != 0) {
JimAioSetError(interp, NULL);
return JIM_ERR;
-int Jim_aioInit(Jim_Interp *interp)
+
+static void JimMakeStdioChannel(Jim_Interp *interp, FILE *fh, const char *name, unsigned flags)
{
- if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
- return JIM_ERR;
+ AioFile *af = JimMakeChannel(interp, fileno(fh), NULL, name, 0, AIO_KEEPOPEN | flags);
+ JimAioSetTaint(af, 0, 0);
+}
+
+int Jim_aioInit(Jim_Interp *interp)
+{
+ Jim_PackageProvideCheck(interp, "aio");
#if defined(JIM_SSL)
- Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL);
+ Jim_RegisterSimpleCmd(interp, "load_ssl_certs", "dir", 1, 1, JimAioLoadSSLCertsCommand);
#endif
- Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
+ Jim_RegisterCmd(interp, "open", "filename ?-noclose? ?mode?", 1, 3, JimAioOpenCommand, NULL, NULL, JIM_CMD_NOTAINT);
#ifdef HAVE_SOCKETS
- Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
+ Jim_RegisterCmd(interp, "socket", "?-async? ?-ipv6? socktype ?address?", 1, 4, JimAioSockCommand, NULL, NULL, JIM_CMD_NOTAINT);
#endif
#ifdef HAVE_PIPE
- Jim_CreateCommand(interp, "pipe", JimAioPipeCommand, NULL, NULL);
+ Jim_RegisterSimpleCmd(interp, "pipe", "", 0, 0, JimAioPipeCommand);
#endif
- JimMakeChannel(interp, fileno(stdin), NULL, "stdin", 0, AIO_KEEPOPEN);
- JimMakeChannel(interp, fileno(stdout), NULL, "stdout", 0, AIO_KEEPOPEN);
- JimMakeChannel(interp, fileno(stderr), NULL, "stderr", 0, AIO_KEEPOPEN | AIO_WBUF_NONE);
+ JimMakeStdioChannel(interp, stdin, "stdin", 0);
+ JimMakeStdioChannel(interp, stdout, "stdout", 0);
+ JimMakeStdioChannel(interp, stderr, "stderr", AIO_WBUF_NONE);
return JIM_OK;
}
nocomplain = 1;
}
if (argc != 2 && !nocomplain) {
- Jim_WrongNumArgs(interp, 1, argv, "?-nocomplain? dirPath");
- return JIM_ERR;
+ return JIM_USAGE;
}
dirPath = Jim_String(argv[1 + nocomplain]);
int Jim_readdirInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "readdir");
- Jim_CreateCommand(interp, "readdir", Jim_ReaddirCmd, NULL, NULL);
+ Jim_RegisterSimpleCmd(interp, "readdir", "?-nocomplain? dirPath", 1, 2, Jim_ReaddirCmd);
return JIM_OK;
}
int opt_indices = 0;
int opt_all = 0;
int opt_inline = 0;
+ int opt_lineanchor = 0;
regex_t *regex;
int match, i, j;
int offset = 0;
int eflags = 0;
int option;
enum {
- OPT_INDICES, OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_INLINE, OPT_START, OPT_END
+ OPT_INDICES, OPT_NOCASE, OPT_LINE, OPT_LINESTOP, OPT_LINEANCHOR, OPT_ALL, OPT_INLINE, OPT_START, OPT_EXPANDED, OPT_END
};
static const char * const options[] = {
- "-indices", "-nocase", "-line", "-all", "-inline", "-start", "--", NULL
+ "-indices", "-nocase", "-line", "-linestop", "-lineanchor", "-all", "-inline", "-start", "-expanded", "--", NULL
};
- if (argc < 3) {
- wrongNumArgs:
- Jim_WrongNumArgs(interp, 1, argv,
- "?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
- return JIM_ERR;
- }
-
for (i = 1; i < argc; i++) {
const char *opt = Jim_String(argv[i]);
if (*opt != '-') {
break;
}
- if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+ if (Jim_GetEnum(interp, argv[i], options, &option, "option", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
return JIM_ERR;
}
if (option == OPT_END) {
case OPT_LINE:
regcomp_flags |= REG_NEWLINE;
+ opt_lineanchor = 1;
break;
+#ifdef REG_NEWLINE_STOP
+ case OPT_LINESTOP:
+ regcomp_flags |= REG_NEWLINE_STOP;
+ break;
+#endif
+#ifdef REG_NEWLINE_ANCHOR
+ case OPT_LINEANCHOR:
+ regcomp_flags |= REG_NEWLINE_ANCHOR;
+ opt_lineanchor = 1;
+ break;
+#endif
case OPT_ALL:
opt_all = 1;
break;
case OPT_START:
if (++i == argc) {
- goto wrongNumArgs;
+ return JIM_USAGE;
}
if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) {
return JIM_ERR;
}
break;
+
+#ifdef REG_EXPANDED
+ case OPT_EXPANDED:
+ regcomp_flags |= REG_EXPANDED;
+ break;
+#endif
+ default:
+
+ Jim_SetResultFormatted(interp, "not supported: %#s", argv[i]);
+ return JIM_ERR;
}
}
if (argc - i < 2) {
- goto wrongNumArgs;
+ return JIM_USAGE;
}
regex = SetRegexpFromAny(interp, argv[i], regcomp_flags);
num_matches++;
- if (opt_all && !opt_inline) {
-
- goto try_next_match;
- }
j = 0;
- for (i += 2; opt_inline ? j < num_vars : i < argc; i++, j++) {
+ for (j = 0; j < num_vars; j++) {
Jim_Obj *resultObj;
if (opt_indices) {
}
else {
- result = Jim_SetVariable(interp, argv[i], resultObj);
+ result = Jim_SetVariable(interp, argv[i + 2 + j], resultObj);
if (result != JIM_OK) {
- Jim_FreeObj(interp, resultObj);
break;
}
}
}
- try_next_match:
- if (opt_all && (pattern[0] != '^' || (regcomp_flags & REG_NEWLINE)) && *source_str) {
+ if (opt_all && (pattern[0] != '^' || opt_lineanchor) && *source_str) {
if (pmatch[0].rm_eo) {
offset += utf8_strlen(source_str, pmatch[0].rm_eo);
source_str += pmatch[0].rm_eo;
const char *pattern;
int option;
enum {
- OPT_NOCASE, OPT_LINE, OPT_ALL, OPT_START, OPT_COMMAND, OPT_END
+ OPT_NOCASE, OPT_LINE, OPT_LINESTOP, OPT_LINEANCHOR, OPT_ALL, OPT_START, OPT_COMMAND, OPT_EXPANDED, OPT_END
};
static const char * const options[] = {
- "-nocase", "-line", "-all", "-start", "-command", "--", NULL
+ "-nocase", "-line", "-linestop", "-lineanchor", "-all", "-start", "-command", "-expanded", "--", NULL
};
- if (argc < 4) {
- wrongNumArgs:
- Jim_WrongNumArgs(interp, 1, argv,
- "?-switch ...? exp string subSpec ?varName?");
- return JIM_ERR;
- }
-
for (i = 1; i < argc; i++) {
const char *opt = Jim_String(argv[i]);
if (*opt != '-') {
break;
}
- if (Jim_GetEnum(interp, argv[i], options, &option, "switch", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
+ if (Jim_GetEnum(interp, argv[i], options, &option, "option", JIM_ERRMSG | JIM_ENUM_ABBREV) != JIM_OK) {
return JIM_ERR;
}
if (option == OPT_END) {
regcomp_flags |= REG_NEWLINE;
break;
+#ifdef REG_NEWLINE_STOP
+ case OPT_LINESTOP:
+ regcomp_flags |= REG_NEWLINE_STOP;
+ break;
+#endif
+#ifdef REG_NEWLINE_ANCHOR
+ case OPT_LINEANCHOR:
+ regcomp_flags |= REG_NEWLINE_ANCHOR;
+ break;
+#endif
case OPT_ALL:
opt_all = 1;
break;
case OPT_START:
if (++i == argc) {
- goto wrongNumArgs;
+ return JIM_USAGE;
}
if (Jim_GetIndex(interp, argv[i], &offset) != JIM_OK) {
return JIM_ERR;
case OPT_COMMAND:
opt_command = 1;
break;
+
+#ifdef REG_EXPANDED
+ case OPT_EXPANDED:
+ regcomp_flags |= REG_EXPANDED;
+ break;
+#endif
+
+ default:
+
+ Jim_SetResultFormatted(interp, "not supported: %#s", argv[i]);
+ return JIM_ERR;
}
}
if (argc - i != 3 && argc - i != 4) {
- goto wrongNumArgs;
+ return JIM_USAGE;
}
regcomp_obj = Jim_DuplicateObj(interp, argv[i]);
- Jim_IncrRefCount(regcomp_obj);
+ Jim_IncrRefCount(regcomp_obj);
regex = SetRegexpFromAny(interp, regcomp_obj, regcomp_flags);
if (!regex) {
- Jim_DecrRefCount(interp, regcomp_obj);
+ Jim_DecrRefCount(interp, regcomp_obj);
return JIM_ERR;
}
pattern = Jim_String(argv[i]);
cmd_prefix = argv[i + 2];
if (Jim_ListLength(interp, cmd_prefix) == 0) {
Jim_SetResultString(interp, "command prefix must be a list of at least one element", -1);
- Jim_DecrRefCount(interp, regcomp_obj);
+ Jim_DecrRefCount(interp, regcomp_obj);
return JIM_ERR;
}
Jim_IncrRefCount(cmd_prefix);
n = source_len - offset;
p = source_str + offset;
- do {
+
+ while (n || pattern[0]) {
int match = jim_regexec(regex, p, MAX_SUB_MATCHES, pmatch, regexec_flags);
if (match >= REG_BADPAT) {
break;
}
+ regexec_flags = 0;
+ if (pmatch[0].rm_eo == pmatch[0].rm_so) {
- if ((regcomp_flags & REG_NEWLINE) == 0 && pattern[0] == '^') {
- break;
- }
-
-
- if (pattern[0] == '\0' && n) {
-
- Jim_AppendString(interp, resultObj, p, 1);
- p++;
- n--;
- }
+ if (pattern[0] == '^') {
- if (pmatch[0].rm_eo == pmatch[0].rm_so) {
+ regexec_flags = REG_NOTBOL;
+ }
+ else {
- regexec_flags = REG_NOTBOL;
- }
- else {
- regexec_flags = 0;
+ int charlen = utf8_charlen(p[0]);
+ Jim_AppendString(interp, resultObj, p, charlen);
+ p += charlen;
+ n -= charlen;
+ }
}
-
- } while (n);
+ }
Jim_AppendString(interp, resultObj, p, -1);
if (result == JIM_OK) {
Jim_SetResultInt(interp, num_matches);
}
- else {
- Jim_FreeObj(interp, resultObj);
- }
}
else {
Jim_SetResult(interp, resultObj);
Jim_DecrRefCount(interp, cmd_prefix);
}
- Jim_DecrRefCount(interp, regcomp_obj);
+ Jim_DecrRefCount(interp, regcomp_obj);
return result;
}
int Jim_regexpInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "regexp");
- Jim_CreateCommand(interp, "regexp", Jim_RegexpCmd, NULL, NULL);
- Jim_CreateCommand(interp, "regsub", Jim_RegsubCmd, NULL, NULL);
+ Jim_RegisterSimpleCmd(interp, "regexp", "?-option ...? exp string ?matchVar? ?subMatchVar ...?", 2, -1, Jim_RegexpCmd);
+ Jim_RegisterSimpleCmd(interp, "regsub", "?-option ...? exp string subSpec ?varName?", 3, -1, Jim_RegsubCmd);
return JIM_OK;
}
continue;
}
- if (errno == EEXIST) {
+ if (errno == EEXIST || errno == ENOTDIR) {
jim_stat_t sb;
if (Jim_Stat(path, &sb) == 0 && S_ISDIR(sb.st_mode)) {
file_cmd_delete,
1,
-1,
+ JIM_MODFLAG_NOTAINT,
},
{ "mkdir",
file_cmd_mkdir,
1,
-1,
+ JIM_MODFLAG_NOTAINT,
},
{ "tempfile",
file_cmd_tempfile,
0,
1,
+ JIM_MODFLAG_NOTAINT,
},
{ "rename",
file_cmd_rename,
2,
3,
+ JIM_MODFLAG_NOTAINT,
},
#if defined(HAVE_LINK) && defined(HAVE_SYMLINK)
static int Jim_CdCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- const char *path;
-
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "dirname");
- return JIM_ERR;
- }
-
- path = Jim_String(argv[1]);
+ const char *path = Jim_String(argv[1]);
if (chdir(path) != 0) {
Jim_SetResultFormatted(interp, "couldn't change working directory to \"%s\": %s", path,
int Jim_fileInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "file");
- Jim_CreateCommand(interp, "file", Jim_SubCmdProc, (void *)file_command_table, NULL);
- Jim_CreateCommand(interp, "pwd", Jim_PwdCmd, NULL, NULL);
- Jim_CreateCommand(interp, "cd", Jim_CdCmd, NULL, NULL);
+ Jim_RegisterSubCmd(interp, "file", file_command_table, NULL);
+ Jim_RegisterSimpleCmd(interp, "pwd", "", 0, 0, Jim_PwdCmd);
+ Jim_RegisterCmd(interp, "cd", "dirname", 1, 1, Jim_CdCmd, NULL, NULL, JIM_CMD_NOTAINT);
return JIM_OK;
}
int Jim_execInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "exec");
- Jim_CreateCommand(interp, "exec", Jim_ExecCmd, NULL, NULL);
+ Jim_RegisterSimpleCmd(interp, "exec", "arg ?arg ...? ?&?", 1, -1, Jim_ExecCmd);
return JIM_OK;
}
#else
static char **JimOriginalEnviron(void);
static char **JimSaveEnv(char **env);
static void JimRestoreEnv(char **env);
-static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
- phandle_t **pidArrayPtr, int *inPipePtr, int *outPipePtr, int *errFilePtr);
+static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, phandle_t **pidArrayPtr,
+ int *outPipePtr, int *errFilePtr);
static void JimDetachPids(struct WaitInfoTable *table, int numPids, const phandle_t *pidPtr);
static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj);
static int Jim_WaitCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
struct WaitInfoTable *table = Jim_Alloc(sizeof(*table));
table->info = NULL;
table->size = table->used = 0;
- table->refcount = 1;
+ table->refcount = 0;
return table;
}
int i;
argc--;
- numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL, NULL);
+ numPids = JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, NULL);
if (numPids < 0) {
return JIM_ERR;
}
}
numPids =
- JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, NULL, &outputId, &errorId);
+ JimCreatePipeline(interp, argc - 1, argv + 1, &pidPtr, &outputId, &errorId);
if (numPids < 0) {
return JIM_ERR;
if (Jim_EvalObjVector(interp, 2, objv) == JIM_OK) {
jim_wide fd;
if (Jim_GetWide(interp, Jim_GetResult(interp), &fd) == JIM_OK) {
- return fd;
+ return dup(fd);
}
}
return -1;
nohang = 1;
}
if (argc != nohang + 2) {
- Jim_WrongNumArgs(interp, 1, argv, "?-nohang? ?pid?");
- return JIM_ERR;
+ return JIM_USAGE;
}
if (Jim_GetLong(interp, argv[nohang + 1], &pid) != JIM_OK) {
return JIM_ERR;
else if (pid < 0) {
pid = phandle;
}
+ else if (phandle == 0) {
+
+ pid = 0;
+ }
#endif
errCodeObj = JimMakeErrorCode(interp, pid, status, NULL);
static int Jim_PidCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 1) {
- Jim_WrongNumArgs(interp, 1, argv, "");
- return JIM_ERR;
- }
-
Jim_SetResultInt(interp, (jim_wide)getpid());
return JIM_OK;
}
-static int
-JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, phandle_t **pidArrayPtr,
- int *inPipePtr, int *outPipePtr, int *errFilePtr)
+#define JIM_ETT_IN 0x0001
+#define JIM_ETT_OUT 0x0002
+#define JIM_ETT_ERR 0x0004
+#define JIM_ETT_PIPE 0x0008
+
+#define JIM_ETT_NOARG 0x0010
+#define JIM_ETT_APPEND 0x0020
+#define JIM_ETT_STR 0x0040
+#define JIM_ETT_DUPERR 0x0080
+#define JIM_ETT_HANDLE 0x0100
+
+#define JIM_ETT_CMD 0xF000
+#define JIM_ETT_BAD 0xF001
+
+struct redir_type_t {
+ const char *prefix;
+ unsigned flags;
+};
+
+
+static const struct redir_type_t redir_types[] = {
+ { "<<@", JIM_ETT_IN | JIM_ETT_HANDLE | JIM_ETT_STR },
+ { "<<", JIM_ETT_IN | JIM_ETT_STR },
+ { "<@", JIM_ETT_IN | JIM_ETT_HANDLE },
+ { "<", JIM_ETT_IN },
+
+ { "2>>", JIM_ETT_ERR | JIM_ETT_APPEND },
+ { "2>@", JIM_ETT_ERR | JIM_ETT_HANDLE },
+ { "2>", JIM_ETT_ERR },
+
+ { ">>&", JIM_ETT_OUT | JIM_ETT_APPEND | JIM_ETT_DUPERR },
+ { ">>", JIM_ETT_OUT | JIM_ETT_APPEND },
+ { ">&@", JIM_ETT_OUT | JIM_ETT_HANDLE | JIM_ETT_DUPERR },
+ { ">@", JIM_ETT_OUT | JIM_ETT_HANDLE },
+ { ">&", JIM_ETT_OUT | JIM_ETT_DUPERR },
+ { ">", JIM_ETT_OUT },
+
+ { "|&", JIM_ETT_PIPE | JIM_ETT_DUPERR },
+ { "|", JIM_ETT_PIPE },
+ { NULL }
+};
+
+static unsigned JimExecClassifyArg(const char *arg)
{
- phandle_t *pidPtr = NULL; /* Points to alloc-ed array holding all
- * the pids of child processes. */
- int numPids = 0; /* Actual number of processes that exist
- * at *pidPtr right now. */
- int cmdCount; /* Count of number of distinct commands
- * found in argc/argv. */
- const char *input = NULL; /* Describes input for pipeline, depending
- * on "inputFile". NULL means take input
- * from stdin/pipe. */
- int input_len = 0;
+ int i;
+ for (i = 0; redir_types[i].prefix; i++) {
+ int len = strlen(redir_types[i].prefix);
+ if (strncmp(arg, redir_types[i].prefix, len) == 0) {
+ if (strlen(arg) > len) {
+ if (redir_types[i].flags & JIM_ETT_NOARG) {
-#define FILE_NAME 0
-#define FILE_APPEND 1
-#define FILE_HANDLE 2
-#define FILE_TEXT 3
+ return JIM_ETT_BAD;
+ }
+ return redir_types[i].flags;
+ }
- int inputFile = FILE_NAME; /* 1 means input is name of input file.
- * 2 means input is filehandle name.
- * 0 means input holds actual
- * text to be input to command. */
+ return redir_types[i].flags | JIM_ETT_NOARG;
+ }
+ }
+ return JIM_ETT_CMD;
+}
- int outputFile = FILE_NAME; /* 0 means output is the name of output file.
- * 1 means output is the name of output file, and append.
+static int JimParsePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *cmdList, Jim_Obj *redirectList)
+{
+ int i;
+
+ int first = 1;
+ const char *arg = NULL;
+
+ for (i = 0; i < argc; i++) {
+ unsigned ett;
+ if (first) {
+ if (Jim_ListLength(interp, argv[i]) == 0) {
+ Jim_SetResultString(interp, "empty command list", -1);
+ return JIM_ERR;
+ }
+ Jim_ListAppendElement(interp, cmdList, argv[i]);
+ first = 0;
+ continue;
+ }
+
+ arg = Jim_String(argv[i]);
+ ett = JimExecClassifyArg(arg);
+ if (ett == JIM_ETT_BAD || ett == JIM_ETT_CMD) {
+ Jim_SetResultFormatted(interp, "invalid redirection %s", arg);
+ return JIM_ERR;
+ }
+ if (ett & JIM_ETT_PIPE) {
+ Jim_ListAppendElement(interp, cmdList, argv[i]);
+ first = 1;
+ continue;
+ }
+ Jim_ListAppendElement(interp, redirectList, argv[i]);
+ if ((ett & JIM_ETT_NOARG)) {
+
+ if (i >= argc - 1) {
+
+ Jim_SetResultFormatted(interp, "can't specify \"%#s\" as last word in command", argv[i]);
+ return -1;
+ }
+ i++;
+ Jim_ListAppendElement(interp, redirectList, argv[i]);
+ }
+ }
+
+ if (first) {
+ if (Jim_ListLength(interp, cmdList)) {
+ Jim_SetResultFormatted(interp, "cmdlist required after %s", arg);
+ }
+ else {
+ Jim_SetResultString(interp, "cmdlist is required", -1);
+ }
+ return JIM_ERR;
+ }
+
+ return JIM_OK;
+}
+
+static int JimParsePipelineLegacy(Jim_Interp *interp, int argc, Jim_Obj *const *argv, Jim_Obj *cmdList, Jim_Obj *redirectList)
+{
+ int i;
+
+ Jim_Obj *cmdObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, cmdList, cmdObj);
+ const char *arg = NULL;
+
+ for (i = 0; i < argc; i++) {
+ arg = Jim_String(argv[i]);
+ unsigned ett = JimExecClassifyArg(arg);
+ if (ett == JIM_ETT_BAD) {
+ Jim_SetResultFormatted(interp, "invalid: %s", arg);
+ return JIM_ERR;
+ }
+ if (ett == JIM_ETT_CMD) {
+
+ Jim_ListAppendElement(interp, cmdObj, argv[i]);
+ continue;
+ }
+ if (ett & JIM_ETT_PIPE) {
+ if (Jim_ListLength(interp, cmdObj) == 0) {
+ goto missing_cmd;
+ }
+
+ Jim_ListAppendElement(interp, cmdList, argv[i]);
+
+ cmdObj = Jim_NewListObj(interp, NULL, 0);
+ Jim_ListAppendElement(interp, cmdList, cmdObj);
+ continue;
+ }
+ Jim_ListAppendElement(interp, redirectList, argv[i]);
+ if ((ett & JIM_ETT_NOARG)) {
+
+ if (i >= argc - 1) {
+
+ Jim_SetResultFormatted(interp, "can't specify \"%#s\" as last word in command", argv[i]);
+ return -1;
+ }
+ i++;
+ Jim_ListAppendElement(interp, redirectList, argv[i]);
+ }
+ }
+
+ if (Jim_ListLength(interp, cmdObj) == 0) {
+missing_cmd:
+ if (arg && *arg == '|') {
+ Jim_SetResultString(interp, "illegal use of | or |& in command", -1);
+ }
+ else {
+ Jim_SetResultString(interp, "didn't specify command to execute", -1);
+ }
+ return JIM_ERR;
+ }
+
+ return JIM_OK;
+}
+
+static int JimExecPipeline(Jim_Interp *interp, Jim_Obj *cmdList, Jim_Obj *redirectList,
+ phandle_t **pidArrayPtr, int *outPipePtr, int *errFilePtr)
+{
+ phandle_t *pidPtr = NULL; /* Points to alloc-ed array holding all
+ * the pids of child processes. */
+ int numPids = 0; /* Actual number of processes that exist
+ * at *pidPtr right now. */
+ int cmdCount; /* Count of number of distinct commands
+ * found in argc/argv. */
+ const char *input = NULL; /* Describes input for pipeline, depending
+ * on "inputFile". NULL means take input
+ * from stdin/pipe. */
+ int input_len = 0;
+
+#define FILE_NAME 0
+#define FILE_APPEND 1
+#define FILE_HANDLE 2
+#define FILE_TEXT 3
+
+ int inputFile = FILE_NAME; /* 1 means input is name of input file.
+ * 2 means input is filehandle name.
+ * 0 means input holds actual
+ * text to be input to command. */
+
+ int outputFile = FILE_NAME; /* 0 means output is the name of output file.
+ * 1 means output is the name of output file, and append.
* 2 means output is filehandle name.
* All this is ignored if output is NULL
*/
int errorId = -1;
int lastOutputId = -1;
int pipeIds[2];
- int firstArg, lastArg; /* Indexes of first and last arguments in
- * current command. */
- int lastBar;
int i;
phandle_t phandle;
char **save_environ;
#endif
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
-
- char **arg_array = Jim_Alloc(sizeof(*arg_array) * (argc + 1));
- int arg_count = 0;
-
- if (inPipePtr != NULL) {
- *inPipePtr = -1;
- }
if (outPipePtr != NULL) {
*outPipePtr = -1;
}
}
pipeIds[0] = pipeIds[1] = -1;
- cmdCount = 1;
- lastBar = -1;
- for (i = 0; i < argc; i++) {
- const char *arg = Jim_String(argv[i]);
-
- if (arg[0] == '<') {
- inputFile = FILE_NAME;
- input = arg + 1;
- if (*input == '<') {
- inputFile = FILE_TEXT;
- input_len = Jim_Length(argv[i]) - 2;
- input++;
- }
- else if (*input == '@') {
- inputFile = FILE_HANDLE;
- input++;
- }
-
- if (!*input && ++i < argc) {
- input = Jim_GetString(argv[i], &input_len);
- }
- }
- else if (arg[0] == '>') {
- int dup_error = 0;
-
- outputFile = FILE_NAME;
-
- output = arg + 1;
- if (*output == '>') {
- outputFile = FILE_APPEND;
- output++;
- }
- if (*output == '&') {
+ int redir_len = Jim_ListLength(interp, redirectList);
+ for (i = 0; i < redir_len; i++) {
+ int len;
+ int item_len;
+ Jim_Obj *redirObj = Jim_ListGetIndex(interp, redirectList, i);
+ const char *arg = Jim_GetString(redirObj, &len);
+ unsigned ett = JimExecClassifyArg(arg);
+ const char *item;
+ int type = FILE_NAME;
+ if ((ett & JIM_ETT_NOARG) == 0) {
- output++;
- dup_error = 1;
+ item = arg + 1;
+ if (ett & JIM_ETT_HANDLE) {
+ item++;
}
- if (*output == '@') {
- outputFile = FILE_HANDLE;
- output++;
- }
- if (!*output && ++i < argc) {
- output = Jim_String(argv[i]);
- }
- if (dup_error) {
- errorFile = outputFile;
- error = output;
+ if (ett & JIM_ETT_APPEND) {
+ item++;
}
- }
- else if (arg[0] == '2' && arg[1] == '>') {
- error = arg + 2;
- errorFile = FILE_NAME;
-
- if (*error == '@') {
- errorFile = FILE_HANDLE;
- error++;
+ if (ett & JIM_ETT_DUPERR) {
+ item++;
}
- else if (*error == '>') {
- errorFile = FILE_APPEND;
- error++;
+ if (ett & JIM_ETT_ERR) {
+ item++;
}
- if (!*error && ++i < argc) {
- error = Jim_String(argv[i]);
+ if (ett & JIM_ETT_STR) {
+ type = FILE_TEXT;
+ item++;
}
+ item_len = len - (item - arg);
}
else {
- if (strcmp(arg, "|") == 0 || strcmp(arg, "|&") == 0) {
- if (i == lastBar + 1 || i == argc - 1) {
- Jim_SetResultString(interp, "illegal use of | or |& in command", -1);
- goto badargs;
- }
- lastBar = i;
- cmdCount++;
- }
- arg_array[arg_count++] = (char *)arg;
- continue;
+ i++;
+ item = Jim_GetString(Jim_ListGetIndex(interp, redirectList, i), &item_len);
}
- if (i >= argc) {
- Jim_SetResultFormatted(interp, "can't specify \"%s\" as last word in command", arg);
- goto badargs;
+ if (ett & JIM_ETT_HANDLE) {
+ type = FILE_HANDLE;
+ }
+ if (ett & JIM_ETT_APPEND) {
+ type = FILE_APPEND;
+ }
+ if (ett & JIM_ETT_STR) {
+ type = FILE_TEXT;
+ }
+ if (ett & JIM_ETT_IN) {
+ input = item;
+ input_len = item_len;
+ inputFile = type;
+ }
+ else if (ett & JIM_ETT_OUT) {
+ output = item;
+ outputFile = type;
+ if (ett & JIM_ETT_DUPERR) {
+ error = output;
+ errorFile = outputFile;
+ }
+ }
+ else if (ett & JIM_ETT_ERR) {
+ error = item;
+ errorFile = type;
}
- }
-
- if (arg_count == 0) {
- Jim_SetResultString(interp, "didn't specify command to execute", -1);
-badargs:
- Jim_Free(arg_array);
- return -1;
}
Jim_Lseek(inputId, 0L, SEEK_SET);
}
else if (inputFile == FILE_HANDLE) {
- int fd = JimGetChannelFd(interp, input);
-
- if (fd < 0) {
+ inputId = JimGetChannelFd(interp, input);
+ if (inputId < 0) {
goto error;
}
- inputId = dup(fd);
}
else {
inputId = Jim_OpenForRead(input);
}
}
}
- else if (inPipePtr != NULL) {
- if (pipe(pipeIds) != 0) {
- Jim_SetResultErrno(interp, "couldn't create input pipe for command");
- goto error;
- }
- inputId = pipeIds[0];
- *inPipePtr = pipeIds[1];
- pipeIds[0] = pipeIds[1] = -1;
- }
if (output != NULL) {
if (outputFile == FILE_HANDLE) {
- int fd = JimGetChannelFd(interp, output);
- if (fd < 0) {
+ lastOutputId = JimGetChannelFd(interp, output);
+ if (lastOutputId < 0) {
goto error;
}
- lastOutputId = dup(fd);
}
else {
lastOutputId = Jim_OpenForWrite(output, outputFile == FILE_APPEND);
pipeIds[0] = pipeIds[1] = -1;
}
+
if (error != NULL) {
if (errorFile == FILE_HANDLE) {
if (strcmp(error, "1") == 0) {
}
}
if (errorId == -1) {
- int fd = JimGetChannelFd(interp, error);
- if (fd < 0) {
+ errorId = JimGetChannelFd(interp, error);
+ if (errorId < 0) {
goto error;
}
- errorId = dup(fd);
}
}
else {
*errFilePtr = dup(errorId);
}
-
+ int cmd_list_size = Jim_ListLength(interp, cmdList);
+ cmdCount = (cmd_list_size + 1) / 2;
pidPtr = Jim_Alloc(cmdCount * sizeof(*pidPtr));
- for (firstArg = 0; firstArg < arg_count; numPids++, firstArg = lastArg + 1) {
- int pipe_dup_err = 0;
- int origErrorId = errorId;
- for (lastArg = firstArg; lastArg < arg_count; lastArg++) {
- if (strcmp(arg_array[lastArg], "|") == 0) {
- break;
- }
- if (strcmp(arg_array[lastArg], "|&") == 0) {
- pipe_dup_err = 1;
- break;
- }
+ for (i = 0; i < cmd_list_size; ) {
+ char **arg_array;
+ int j;
+ int origErrorId = errorId;
+ Jim_Obj *cmdObj = Jim_ListGetIndex(interp, cmdList, i++);
+ int cmd_len = Jim_ListLength(interp, cmdObj);
+ Jim_Obj *sepObj = NULL;
+ if (i < cmd_list_size - 1) {
+ sepObj = Jim_ListGetIndex(interp, cmdList, i++);
}
- if (lastArg == firstArg) {
- Jim_SetResultString(interp, "missing command to exec", -1);
- goto error;
- }
+ arg_array = Jim_Alloc((cmd_len + 1) * sizeof(*arg_array));
+ for (j = 0; j < cmd_len; j++) {
+ arg_array[j] = (char *)Jim_String(Jim_ListGetIndex(interp, cmdObj, j));
+ }
+ arg_array[j] = NULL;
- arg_array[lastArg] = NULL;
- if (lastArg == arg_count) {
+ if (sepObj == NULL) {
outputId = lastOutputId;
lastOutputId = -1;
}
else {
if (pipe(pipeIds) != 0) {
Jim_SetResultErrno(interp, "couldn't create pipe");
+ Jim_Free(arg_array);
goto error;
}
outputId = pipeIds[1];
}
- if (pipe_dup_err) {
+ if (sepObj && Jim_CompareStringImmediate(interp, sepObj, "|&")) {
errorId = outputId;
}
#ifdef __MINGW32__
- phandle = JimStartWinProcess(interp, &arg_array[firstArg], save_environ, inputId, outputId, errorId);
+ phandle = JimStartWinProcess(interp, &arg_array[0], save_environ, inputId, outputId, errorId);
if (phandle == JIM_BAD_PHANDLE) {
- Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[firstArg]);
+ Jim_SetResultFormatted(interp, "couldn't exec \"%s\"", arg_array[0]);
goto error;
}
#else
- i = strlen(arg_array[firstArg]);
+ int argv0_len = strlen(arg_array[0]);
#ifdef HAVE_EXECVPE
child_environ = Jim_GetEnviron();
close(lastOutputId);
}
- execvpe(arg_array[firstArg], &arg_array[firstArg], child_environ);
+ execvpe(arg_array[0], arg_array, child_environ);
if (write(fileno(stderr), "couldn't exec \"", 15) &&
- write(fileno(stderr), arg_array[firstArg], i) &&
+ write(fileno(stderr), arg_array[0], argv0_len) &&
write(fileno(stderr), "\"\n", 2)) {
}
#endif
+ Jim_Free(arg_array);
if (table->used == table->size) {
table->size += WAIT_TABLE_GROW_BY;
table->info[table->used].flags = 0;
table->used++;
- pidPtr[numPids] = phandle;
+ pidPtr[numPids++] = phandle;
errorId = origErrorId;
if (errorId != -1) {
close(errorId);
}
- Jim_Free(arg_array);
JimRestoreEnv(save_environ);
error:
- if ((inPipePtr != NULL) && (*inPipePtr != -1)) {
- close(*inPipePtr);
- *inPipePtr = -1;
- }
if ((outPipePtr != NULL) && (*outPipePtr != -1)) {
close(*outPipePtr);
*outPipePtr = -1;
goto cleanup;
}
+static int
+JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv, phandle_t **pidArrayPtr,
+ int *outPipePtr, int *errFilePtr)
+{
+ int rc = -1;
+ int ret;
+
+ Jim_Obj *cmdList = Jim_NewListObj(interp, NULL, 0);
+ Jim_Obj *redirectList = Jim_NewListObj(interp, NULL, 0);
+ Jim_IncrRefCount(cmdList);
+ Jim_IncrRefCount(redirectList);
+
+ if (argc > 1 && Jim_CompareStringImmediate(interp, argv[0], "|")) {
+
+ ret = JimParsePipeline(interp, argc - 1, argv + 1, cmdList, redirectList);
+ }
+ else {
+
+ ret = JimParsePipelineLegacy(interp, argc, argv, cmdList, redirectList);
+ }
+ if (ret == JIM_OK) {
+
+ rc = JimExecPipeline(interp, cmdList, redirectList, pidArrayPtr, outPipePtr, errFilePtr);
+ }
+ Jim_DecrRefCount(interp, cmdList);
+ Jim_DecrRefCount(interp, redirectList);
+ return rc;
+}
+
static int JimCleanupChildren(Jim_Interp *interp, int numPids, phandle_t *pidPtr, Jim_Obj *errStrObj)
{
Jim_PackageProvideCheck(interp, "exec");
waitinfo = JimAllocWaitInfoTable();
- Jim_CreateCommand(interp, "exec", Jim_ExecCmd, waitinfo, JimFreeWaitInfoTable);
+ Jim_RegisterCmd(interp, "exec", "arg ?arg ...? ?&?", 1, -1, Jim_ExecCmd, JimFreeWaitInfoTable, waitinfo, JIM_CMD_NOTAINT);
waitinfo->refcount++;
- Jim_CreateCommand(interp, "wait", Jim_WaitCommand, waitinfo, JimFreeWaitInfoTable);
- Jim_CreateCommand(interp, "pid", Jim_PidCommand, 0, 0);
+ Jim_RegisterCmd(interp, "wait", "?-nohang? ?pid?", 0, 2, Jim_WaitCommand, JimFreeWaitInfoTable, waitinfo, 0);
+ waitinfo->refcount++;
+ Jim_RegisterSimpleCmd(interp, "pid", "", 0, 0, Jim_PidCommand);
return JIM_OK;
}
int Jim_clockInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "clock");
- Jim_CreateCommand(interp, "clock", Jim_SubCmdProc, (void *)clock_command_table, NULL);
+ Jim_RegisterSubCmd(interp, "clock", clock_command_table, NULL);
return JIM_OK;
}
int Jim_arrayInit(Jim_Interp *interp)
{
Jim_PackageProvideCheck(interp, "array");
- Jim_CreateCommand(interp, "array", Jim_SubCmdProc, (void *)array_command_table, NULL);
+ Jim_RegisterSubCmd(interp, "array", array_command_table, NULL);
return JIM_OK;
}
int Jim_InitStaticExtensions(Jim_Interp *interp)
#define JIM_INTEGER_SPACE 24
-#if defined(DEBUG_SHOW_SCRIPT) || defined(DEBUG_SHOW_SCRIPT_TOKENS) || defined(JIM_DEBUG_COMMAND) || defined(DEBUG_SHOW_SUBST)
+#if defined(DEBUG_SHOW_SCRIPT) || defined(DEBUG_SHOW_SCRIPT_TOKENS) || defined(JIM_DEBUG_COMMAND) || defined(DEBUG_SHOW_EXPR_TOKENS) || defined(DEBUG_SHOW_EXPR)
+#define JIM_TT_NAME
static const char *jim_tt_name(int type);
#endif
static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv);
static Jim_VarVal *JimFindVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr);
static int SetVariableFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+static int JimCallNative(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv);
#define JIM_DICT_SUGAR 100
int i;
int l1bytelen;
- if (!l1 || !l2 || l1 > l2) {
+ if (!l1 || !l2 || l1 > l2 || idx > l2) {
return -1;
}
if (idx < 0)
free(ptr);
return NULL;
}
+ else if (ptr) {
+ return realloc(ptr, size);
+ }
else {
- void *p = realloc(ptr, size);
- if( p==0 ){
- fprintf(stderr,"Out of memory\n");
- exit(1);
- }
- return p;
+ return malloc(size);
}
}
JimAssocDataHashTableValueDestructor
};
-void Jim_InitStack(Jim_Stack *stack)
+void Jim_StackInit(Jim_Stack *stack, void (*freefunc) (void *ptr))
{
stack->len = 0;
stack->maxlen = 0;
stack->vector = NULL;
+ stack->freefunc = freefunc;
}
-void Jim_FreeStack(Jim_Stack *stack)
+void Jim_StackFree(Jim_Stack *stack)
{
- Jim_Free(stack->vector);
-}
+ int i;
-int Jim_StackLen(Jim_Stack *stack)
-{
- return stack->len;
+ if (stack->freefunc) {
+ for (i = 0; i < stack->len; i++) {
+ stack->freefunc(stack->vector[i]);
+ }
+ }
+ Jim_Free(stack->vector);
}
void Jim_StackPush(Jim_Stack *stack, void *element)
return stack->vector[stack->len];
}
-void *Jim_StackPeek(Jim_Stack *stack)
-{
- if (stack->len == 0)
- return NULL;
- return stack->vector[stack->len - 1];
-}
-
-void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
-{
- int i;
-
- for (i = 0; i < stack->len; i++)
- freeFunc(stack->vector[i]);
-}
-
#define JIM_TT_NONE 0
}
objPtr->refCount = 0;
+ objPtr->taint = interp->taint;
objPtr->prevObjPtr = NULL;
Jim_Obj *dupPtr;
dupPtr = Jim_NewObj(interp);
+ dupPtr->taint = objPtr->taint;
+
if (objPtr->bytes == NULL) {
dupPtr->bytes = NULL;
int len;
const char *str = Jim_GetString(appendObjPtr, &len);
Jim_AppendString(interp, objPtr, str, len);
+ objPtr->taint |= appendObjPtr->taint;
}
void Jim_AppendStrings(Jim_Interp *interp, Jim_Obj *objPtr, ...)
const char *sA = Jim_GetString(aObjPtr, &Alen);
const char *sB = Jim_GetString(bObjPtr, &Blen);
- return Alen == Blen && memcmp(sA, sB, Alen) == 0;
+ return Alen == Blen && *sA == *sB && memcmp(sA, sB, Alen) == 0;
}
}
}
}
+
static int qsortCompareStringPointers(const void *a, const void *b)
{
char *const *sa = (char *const *)a;
char *const *sb = (char *const *)b;
+
+ if (strcmp(*sa, "--") == 0) {
+ return 1;
+ }
+ if (strcmp(*sb, "--") == 0) {
+
+ return -1;
+ }
+
return strcmp(*sa, *sb);
}
ParseTokenList tokenlist;
Jim_Obj *fileNameObj;
int line;
+ int oldtaint;
fileNameObj = Jim_GetSourceInfo(interp, objPtr, &line);
ScriptAddToken(&tokenlist, scriptText + scriptTextLen, 0, JIM_TT_EOF, 0);
+
+
+ oldtaint = interp->taint;
+ interp->taint = objPtr->taint;
+
script = Jim_Alloc(sizeof(*script));
memset(script, 0, sizeof(*script));
script->inUse = 1;
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, script);
objPtr->typePtr = &scriptObjType;
+
+ interp->taint = oldtaint;
}
static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
static void JimDecrCmdRefCount(Jim_Interp *interp, Jim_Cmd *cmdPtr)
{
if (--cmdPtr->inUse == 0) {
- if (cmdPtr->isproc) {
+ if (cmdPtr->flags & JIM_CMD_ISPROC) {
Jim_DecrRefCount(interp, cmdPtr->u.proc.argListObjPtr);
Jim_DecrRefCount(interp, cmdPtr->u.proc.bodyObjPtr);
Jim_DecrRefCount(interp, cmdPtr->u.proc.nsObj);
int len1, len2;
const char *str1 = Jim_GetStringNoQualifier((Jim_Obj *)key1, &len1);
const char *str2 = Jim_GetStringNoQualifier((Jim_Obj *)key2, &len2);
- return len1 == len2 && memcmp(str1, str2, len1) == 0;
+ return len1 == len2 && *str1 == *str2 && memcmp(str1, str2, len1) == 0;
}
static void JimCommandsHT_ValDestructor(void *interp, void *val)
Jim_ReplaceHashEntry(&interp->commands, nameObjPtr, cmd);
}
-int Jim_CreateCommandObj(Jim_Interp *interp, Jim_Obj *cmdNameObj,
- Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
+
+Jim_Cmd *Jim_RegisterCommand(Jim_Interp *interp, Jim_Obj *cmdNameObj,
+ Jim_CmdProc *cmdProc,
+ Jim_DelCmdProc *delProc,
+ const char *usage,
+ const char *help,
+ short minargs,
+ short maxargs,
+ int flags,
+ void *privData)
{
+ JimPanic(((flags & JIM_CMD_ISPROC), "Jim_RegisterCommand called with JIM_CMD_ISPROC flag"));
Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
memset(cmdPtr, 0, sizeof(*cmdPtr));
cmdPtr->inUse = 1;
+ cmdPtr->flags = flags;
cmdPtr->u.native.delProc = delProc;
cmdPtr->u.native.cmdProc = cmdProc;
+ cmdPtr->u.native.usage = usage;
+ cmdPtr->u.native.help = help;
+ cmdPtr->u.native.minargs = minargs;
+ cmdPtr->u.native.maxargs = maxargs;
cmdPtr->u.native.privData = privData;
Jim_IncrRefCount(cmdNameObj);
JimCreateCommand(interp, cmdNameObj, cmdPtr);
Jim_DecrRefCount(interp, cmdNameObj);
- return JIM_OK;
+ return cmdPtr;
}
-
int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
{
- return Jim_CreateCommandObj(interp, Jim_NewStringObj(interp, cmdNameStr, -1), cmdProc, privData, delProc);
+ Jim_RegisterCmd(interp, cmdNameStr, NULL, 0, -1, cmdProc, delProc, privData, 0);
+ return JIM_OK;
}
static int JimCreateProcedureStatics(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *staticsListObjPtr)
}
else {
initObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_NONE);
+ if (!initObjPtr) {
+ Jim_SetResultFormatted(interp, "Could not resolve upvar \"%#s\"'s value", nameObjPtr);
+ Jim_DecrRefCount(interp, nameObjPtr);
+ return JIM_ERR;
+ }
}
break;
static void JimUpdateProcNamespace(Jim_Interp *interp, Jim_Cmd *cmdPtr, Jim_Obj *nameObjPtr)
{
#ifdef jim_ext_namespace
- if (cmdPtr->isproc) {
+ if (cmdPtr->flags & JIM_CMD_ISPROC) {
int len;
const char *cmdname = Jim_GetStringNoQualifier(nameObjPtr, &len);
assert(cmdPtr);
memset(cmdPtr, 0, sizeof(*cmdPtr));
cmdPtr->inUse = 1;
- cmdPtr->isproc = 1;
+ cmdPtr->flags = JIM_CMD_ISPROC;
cmdPtr->u.proc.argListObjPtr = argListObjPtr;
cmdPtr->u.proc.argListLen = argListLen;
cmdPtr->u.proc.bodyObjPtr = bodyObjPtr;
Jim_IncrRefCount(interp->framePtr->nsObj);
Jim_DecrRefCount(interp, qualifiedNameObj);
}
- while (cmd->u.proc.upcall) {
+ while ((cmd->flags & JIM_CMD_ISPROC) && cmd->u.proc.upcall) {
cmd = cmd->prevCmd;
}
return cmd;
static int JimDictSugarSet(Jim_Interp *interp, Jim_Obj *ObjPtr, Jim_Obj *valObjPtr);
-static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *ObjPtr, int flags);
+static Jim_Obj *JimDictSugarGet(Jim_Interp *interp, Jim_Obj *objPtr, int flags);
static int JimSetNewVariable(Jim_HashTable *ht, Jim_Obj *nameObjPtr, Jim_VarVal *vv)
{
int Jim_SetVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, Jim_Obj *valObjPtr)
{
- int err;
+ int ret = JIM_OK;
Jim_VarVal *vv;
switch (SetVariableFromAny(interp, nameObjPtr)) {
case JIM_DICT_SUGAR:
- return JimDictSugarSet(interp, nameObjPtr, valObjPtr);
+ ret = JimDictSugarSet(interp, nameObjPtr, valObjPtr);
+ break;
case JIM_ERR:
- JimCreateVariable(interp, nameObjPtr, valObjPtr);
+ if (JimCreateVariable(interp, nameObjPtr, valObjPtr) == NULL) {
+ ret = JIM_ERR;
+ }
break;
case JIM_OK:
savedCallFrame = interp->framePtr;
interp->framePtr = vv->linkFramePtr;
- err = Jim_SetVariable(interp, vv->objPtr, valObjPtr);
+ ret = Jim_SetVariable(interp, vv->objPtr, valObjPtr);
interp->framePtr = savedCallFrame;
- if (err != JIM_OK)
- return err;
}
+ break;
}
- return JIM_OK;
+ if (ret != JIM_OK && valObjPtr->refCount == 0) {
+
+ Jim_FreeNewObj(interp, valObjPtr);
+ }
+ return ret;
}
int Jim_SetVariableStr(Jim_Interp *interp, const char *name, Jim_Obj *objPtr)
JimPanic((p == NULL, "JimDictSugarParseVarKey() called for non-dict-sugar (%s)", str));
varObjPtr = Jim_NewStringObj(interp, str, p - str);
+ varObjPtr->taint = objPtr->taint;
p++;
keyLen = (str + len) - p;
keyObjPtr = Jim_NewStringObj(interp, p, keyLen);
+ keyObjPtr->taint = objPtr->taint;
Jim_IncrRefCount(varObjPtr);
Jim_IncrRefCount(keyObjPtr);
}
Jim_DecrRefCount(interp, cmdNameObj);
}
- Jim_FreeStack(localCommands);
+ Jim_StackFree(localCommands);
Jim_Free(localCommands);
}
return JIM_OK;
if (frame == interp->evalFrame || (frame->cmd && frame->cmd->cmdNameObj)) {
Jim_EvalFrame *e;
for (e = frame->parent; e; e = e->parent) {
- if (e->cmd && e->cmd->isproc && e->cmd->cmdNameObj) {
+ if (e->cmd && (e->cmd->flags & JIM_CMD_ISPROC) && e->cmd->cmdNameObj) {
break;
}
}
Jim_IncrRefCount(stackTraceObj);
Jim_DecrRefCount(interp, interp->stackTrace);
interp->stackTrace = stackTraceObj;
- interp->errorFlag = 1;
+ interp->hasErrorStackTrace = 1;
}
static void JimSetErrorStack(Jim_Interp *interp, ScriptObj *script)
{
- if (!interp->errorFlag) {
+ if (!interp->hasErrorStackTrace) {
int i;
Jim_Obj *stackTrace = Jim_NewListObj(interp, NULL, 0);
objPtr = Jim_NewObj(interp);
objPtr->typePtr = &intObjType;
objPtr->bytes = NULL;
+ objPtr->taint = 0;
objPtr->internalRep.wideValue = wideValue;
return objPtr;
}
objPtr = Jim_NewObj(interp);
objPtr->typePtr = &doubleObjType;
objPtr->bytes = NULL;
+ objPtr->taint = 0;
objPtr->internalRep.doubleValue = doubleValue;
return objPtr;
}
continue;
elementPtr = JimParserGetTokenObj(interp, &parser);
Jim_SetSourceInfo(interp, elementPtr, fileNameObj, parser.tline);
+ elementPtr->taint = objPtr->taint;
ListAppendElement(objPtr, elementPtr);
}
}
objPtr = Jim_NewObj(interp);
objPtr->typePtr = &listObjType;
objPtr->bytes = NULL;
+ objPtr->taint = 0;
objPtr->internalRep.listValue.ele = NULL;
objPtr->internalRep.listValue.len = 0;
objPtr->internalRep.listValue.maxLen = 0;
memmove(point + elemc, point, (currentLen - idx) * sizeof(Jim_Obj *));
for (i = 0; i < elemc; ++i) {
point[i] = elemVec[i];
+ listPtr->taint |= point[i]->taint;
Jim_IncrRefCount(point[i]);
}
listPtr->internalRep.listValue.len += elemc;
idx = listPtr->internalRep.listValue.len + idx;
Jim_DecrRefCount(interp, listPtr->internalRep.listValue.ele[idx]);
listPtr->internalRep.listValue.ele[idx] = newObjPtr;
+ listPtr->taint |= newObjPtr->taint;
Jim_IncrRefCount(newObjPtr);
return JIM_OK;
}
goto err;
Jim_InvalidateStringRep(objPtr);
Jim_InvalidateStringRep(varObjPtr);
- if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK)
- goto err;
+ if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
+ return JIM_ERR;
+ }
Jim_SetResult(interp, varObjPtr);
return JIM_OK;
err:
dict->table[dict->len++] = valueObjPtr;
}
+ objPtr->taint |= keyObjPtr->taint | valueObjPtr->taint;
return JIM_OK;
}
}
}
varObjPtr = objPtr = Jim_NewDictObj(interp, NULL, 0);
if (Jim_SetVariable(interp, varNamePtr, objPtr) != JIM_OK) {
- Jim_FreeNewObj(interp, varObjPtr);
return JIM_ERR;
}
}
goto err;
}
}
+ if (newObjPtr) {
+ varObjPtr->taint |= newObjPtr->taint;
+ }
break;
}
Jim_InvalidateStringRep(objPtr);
Jim_InvalidateStringRep(varObjPtr);
if (Jim_SetVariable(interp, varNamePtr, varObjPtr) != JIM_OK) {
- goto err;
+ return JIM_ERR;
}
if (!(flags & JIM_NORESULT)) {
else if (idx < 0) {
idx = -INT_MAX;
}
+ else if (idx > INT_MAX) {
+ goto badindex;
+ }
Jim_FreeIntRep(interp, objPtr);
JIM_EXPROP_STREQ,
JIM_EXPROP_STRNE,
+ JIM_EXPROP_STRGLOB,
+ JIM_EXPROP_STRRE,
+
JIM_EXPROP_STRIN,
JIM_EXPROP_STRNI,
JIM_EXPROP_STRLT,
case JIM_EXPROP_NOT:
wC = !bA;
break;
+ case JIM_EXPROP_UNARYPLUS:
+ case JIM_EXPROP_UNARYMINUS:
+ rc = JIM_ERR;
+ Jim_SetResultFormatted(interp,
+ "can't use non-numeric string as operand of \"%s\"",
+ node->type == JIM_EXPROP_UNARYPLUS ? "+" : "-");
+ break;
default:
abort();
}
return 0;
}
+static int JimRegexpMatch(Jim_Interp *interp, Jim_Obj *patternObj, Jim_Obj *objPtr)
+{
+ Jim_Obj *argv[3];
+ int argc = 0;
+ long eq;
+ int rc;
+
+ argv[argc++] = Jim_NewStringObj(interp, "regexp", -1);
+ argv[argc++] = patternObj;
+ argv[argc++] = objPtr;
+
+ rc = Jim_EvalObjVector(interp, argc, argv);
+
+ if (rc != JIM_OK || Jim_GetLong(interp, Jim_GetResult(interp), &eq) != JIM_OK) {
+ eq = -rc;
+ }
+ return eq;
+}
static int JimExprOpStrBin(Jim_Interp *interp, struct JimExprNode *node)
{
case JIM_EXPROP_STRNI:
wC = !JimSearchList(interp, B, A);
break;
+ case JIM_EXPROP_STRGLOB:
+ wC = Jim_StringMatchObj(interp, B, A, 0);
+ break;
+ case JIM_EXPROP_STRRE:
+ wC = JimRegexpMatch(interp, B, A);
+ if (wC < 0) {
+ rc = JIM_ERR;
+ goto error;
+ }
+ break;
default:
abort();
}
Jim_SetResultInt(interp, wC);
+error:
Jim_DecrRefCount(interp, A);
Jim_DecrRefCount(interp, B);
OPRINIT("eq", 60, 2, JimExprOpStrBin),
OPRINIT("ne", 60, 2, JimExprOpStrBin),
+ OPRINIT("=*", 60, 2, JimExprOpStrBin),
+ OPRINIT("=~", 60, 2, JimExprOpStrBin),
OPRINIT("in", 55, 2, JimExprOpStrBin),
OPRINIT("ni", 55, 2, JimExprOpStrBin),
builder.nodes = Jim_Alloc(sizeof(struct JimExprNode) * (tokenlist->count - 1));
memset(builder.nodes, 0, sizeof(struct JimExprNode) * (tokenlist->count - 1));
builder.next = builder.nodes;
- Jim_InitStack(&builder.stack);
+ Jim_StackInit(&builder.stack, NULL);
rc = ExprTreeBuildTree(interp, &builder, 0, 0, 1);
}
- Jim_FreeStack(&builder.stack);
+ Jim_StackFree(&builder.stack);
if (rc != JIM_OK) {
ExprTreeFreeNodes(interp, builder.nodes, builder.next - builder.nodes);
exprText = Jim_GetString(objPtr, &exprTextLen);
+ int oldtaint = interp->taint;
+ interp->taint = objPtr->taint;
+
ScriptTokenListInit(&tokenlist);
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, expr);
objPtr->typePtr = &exprObjType;
+
+ interp->taint = oldtaint;
+
return rc;
}
jim_wide wideValue, increment = 1;
Jim_Obj *intObjPtr;
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?increment?");
- return JIM_ERR;
- }
if (argc == 3) {
if (Jim_GetWideExpr(interp, argv[2], &increment) != JIM_OK)
return JIM_ERR;
if (!intObjPtr || Jim_IsShared(intObjPtr)) {
intObjPtr = Jim_NewIntObj(interp, wideValue + increment);
if (Jim_SetVariable(interp, argv[1], intObjPtr) != JIM_OK) {
- Jim_FreeNewObj(interp, intObjPtr);
return JIM_ERR;
}
}
(retcode = JimTraceCallback(interp, "cmd", objc, objv)) == JIM_OK) {
Jim_SetEmptyResult(interp);
- if (cmdPtr->isproc) {
+ interp->taint = Jim_CalcTaint(objc, objv);
+ if (cmdPtr->flags & JIM_CMD_ISPROC) {
retcode = JimCallProcedure(interp, cmdPtr, objc, objv);
}
+ else if ((cmdPtr->flags & JIM_CMD_NOTAINT) && Jim_CheckTaint(interp, JIM_TAINT_ANY)) {
+ Jim_SetTaintError(interp, 1, objv);
+ retcode = JIM_ERR;
+ }
else {
- interp->cmdPrivData = cmdPtr->u.native.privData;
- retcode = cmdPtr->u.native.cmdProc(interp, objc, objv);
+ retcode = JimCallNative(interp, cmdPtr, objc, objv);
+
}
if (retcode == JIM_ERR) {
JimSetErrorStack(interp, NULL);
Jim_Obj *sintv[JIM_EVAL_SINTV_LEN];
Jim_Obj *objPtr;
char *s;
+ int taint = 0;
+ const char *error_action = NULL;
if (tokens <= JIM_EVAL_SINTV_LEN)
intv = sintv;
tokens = i;
continue;
}
-
+ error_action = "break";
case JIM_CONTINUE:
if (flags & JIM_SUBST_FLAG) {
intv[i] = NULL;
continue;
}
-
+ if (!error_action) {
+ error_action = "continue";
+ }
default:
while (i--) {
if (intv != sintv) {
Jim_Free(intv);
}
+ if (error_action) {
+ Jim_SetResultFormatted(interp, "invoked \"%s\" outside of a loop", error_action);
+ }
return NULL;
}
+ taint |= intv[i]->taint;
Jim_IncrRefCount(intv[i]);
Jim_String(intv[i]);
totlen += intv[i]->length;
}
objPtr = Jim_NewStringObjNoAlloc(interp, NULL, 0);
+ objPtr->taint = taint;
if (tokens == 4 && token[0].type == JIM_TT_ESC && token[1].type == JIM_TT_ESC
&& token[2].type == JIM_TT_VAR) {
return objPtr;
}
+#define JIM_LSUBST_LINE 0x0001
-static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
+static int JimListSubstObj(Jim_Interp *interp, struct Jim_Obj *objPtr, unsigned flags)
{
+ int i;
+ ScriptObj *script;
+ ScriptToken *token;
+ Jim_Obj *resultListObj;
int retcode = JIM_OK;
- Jim_EvalFrame frame;
+
+ Jim_IncrRefCount(objPtr);
+ script = JimGetScript(interp, objPtr);
+ if (JimParseCheckMissing(interp, script->missing) == JIM_ERR) {
+ JimSetErrorStack(interp, script);
+ Jim_DecrRefCount(interp, objPtr);
+ return JIM_ERR;
+ }
+
+ token = script->token;
+
+ script->inUse++;
+
+
+ resultListObj = Jim_NewListObj(interp, NULL, 0);
+
+
+ for (i = 0; i < script->len && retcode == JIM_OK; ) {
+ int argc;
+ int j;
+ Jim_Obj *lineListObj = resultListObj;
+
+
+ argc = token[i].objPtr->internalRep.scriptLineValue.argc;
+ script->linenr = token[i].objPtr->internalRep.scriptLineValue.line;
+
+
+ i++;
+
+ if (flags & JIM_LSUBST_LINE) {
+ lineListObj = Jim_NewListObj(interp, NULL, 0);
+ }
+
+
+ for (j = 0; j < argc; j++) {
+ long wordtokens = 1;
+ int expand = 0;
+ Jim_Obj *wordObjPtr = NULL;
+
+ if (token[i].type == JIM_TT_WORD) {
+ wordtokens = JimWideValue(token[i++].objPtr);
+ if (wordtokens < 0) {
+ expand = 1;
+ wordtokens = -wordtokens;
+ }
+ }
+
+
+ wordObjPtr = JimInterpolateTokens(interp, token + i, wordtokens, JIM_NONE);
+
+ if (!wordObjPtr) {
+ if (retcode == JIM_OK) {
+ retcode = JIM_ERR;
+ }
+ break;
+ }
+
+ Jim_IncrRefCount(wordObjPtr);
+ i += wordtokens;
+
+ if (!expand) {
+ Jim_ListAppendElement(interp, lineListObj, wordObjPtr);
+ }
+ else {
+ int k;
+
+ for (k = 0; k < Jim_ListLength(interp, wordObjPtr); k++) {
+ Jim_ListAppendElement(interp, lineListObj, Jim_ListGetIndex(interp, wordObjPtr, k));
+ }
+ }
+ Jim_DecrRefCount(interp, wordObjPtr);
+ }
+
+ if (flags & JIM_LSUBST_LINE) {
+ Jim_ListAppendElement(interp, resultListObj, lineListObj);
+ }
+ }
+
+ Jim_FreeIntRep(interp, objPtr);
+ objPtr->typePtr = &scriptObjType;
+ Jim_SetIntRepPtr(objPtr, script);
+ Jim_DecrRefCount(interp, objPtr);
+
+ if (retcode == JIM_OK) {
+ Jim_SetResult(interp, resultListObj);
+ }
+ else {
+ Jim_FreeNewObj(interp, resultListObj);
+ }
+
+ return retcode;
+}
+
+static int JimEvalObjList(Jim_Interp *interp, Jim_Obj *listPtr)
+{
+ int retcode = JIM_OK;
+ Jim_EvalFrame frame;
JimPanic((Jim_IsList(listPtr) == 0, "JimEvalObjList() invoked on non-list."));
}
if (script->len == 3
&& token[1].objPtr->typePtr == &commandObjType
- && token[1].objPtr->internalRep.cmdValue.cmdPtr->isproc == 0
+ && (token[1].objPtr->internalRep.cmdValue.cmdPtr->flags & JIM_CMD_ISPROC) == 0
&& token[1].objPtr->internalRep.cmdValue.cmdPtr->u.native.cmdProc == Jim_IncrCoreCommand
&& token[2].objPtr->typePtr == &variableObjType) {
JimPushEvalFrame(interp, &frame, scriptObjPtr);
- interp->errorFlag = 0;
+ interp->hasErrorStackTrace = 0;
argv = sargv;
for (i = 0; i < script->len && retcode == JIM_OK; ) {
if (retcode == JIM_OK && argc) {
retcode = JimInvokeCommand(interp, argc, argv);
+ interp->taint = 0;
if (Jim_CheckSignal(interp)) {
retcode = JIM_SIGNAL;
return retcode;
}
-static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
+static Jim_Obj *JimCmdUsage(Jim_Interp *interp, Jim_Obj *cmdNameObj, Jim_Cmd *cmd)
{
+ Jim_Obj *usage = Jim_DuplicateObj(interp, cmdNameObj);
- Jim_Obj *argmsg = Jim_NewStringObj(interp, "", 0);
- int i;
-
- for (i = 0; i < cmd->u.proc.argListLen; i++) {
- Jim_AppendString(interp, argmsg, " ", 1);
+ if (cmd->flags & JIM_CMD_ISPROC) {
+ int i;
+ for (i = 0; i < cmd->u.proc.argListLen; i++) {
+ Jim_AppendString(interp, usage, " ", 1);
- if (i == cmd->u.proc.argsPos) {
- if (cmd->u.proc.arglist[i].defaultObjPtr) {
+ if (i == cmd->u.proc.argsPos) {
+ if (cmd->u.proc.arglist[i].defaultObjPtr) {
- Jim_AppendString(interp, argmsg, "?", 1);
- Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].defaultObjPtr);
- Jim_AppendString(interp, argmsg, " ...?", -1);
- }
- else {
+ Jim_AppendString(interp, usage, "?", 1);
+ Jim_AppendObj(interp, usage, cmd->u.proc.arglist[i].defaultObjPtr);
+ Jim_AppendString(interp, usage, " ...?", -1);
+ }
+ else {
- Jim_AppendString(interp, argmsg, "?arg ...?", -1);
- }
- }
- else {
- if (cmd->u.proc.arglist[i].defaultObjPtr) {
- Jim_AppendString(interp, argmsg, "?", 1);
- Jim_AppendObj(interp, argmsg, cmd->u.proc.arglist[i].nameObjPtr);
- Jim_AppendString(interp, argmsg, "?", 1);
+ Jim_AppendString(interp, usage, "?arg ...?", -1);
+ }
}
else {
- const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr);
- if (*arg == '&') {
- arg++;
+ if (cmd->u.proc.arglist[i].defaultObjPtr) {
+ Jim_AppendString(interp, usage, "?", 1);
+ Jim_AppendObj(interp, usage, cmd->u.proc.arglist[i].nameObjPtr);
+ Jim_AppendString(interp, usage, "?", 1);
+ }
+ else {
+ const char *arg = Jim_String(cmd->u.proc.arglist[i].nameObjPtr);
+ if (*arg == '&') {
+ arg++;
+ }
+ Jim_AppendString(interp, usage, arg, -1);
}
- Jim_AppendString(interp, argmsg, arg, -1);
}
}
}
- Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s%#s\"", procNameObj, argmsg);
+ else if (cmd->u.native.usage) {
+ if (*cmd->u.native.usage) {
+ Jim_AppendStrings(interp, usage, " ", cmd->u.native.usage, NULL);
+ }
+ }
+ else {
+ Jim_AppendString(interp, usage, " ...", -1);
+ }
+
+ return usage;
+}
+
+static void JimSetProcWrongArgs(Jim_Interp *interp, Jim_Obj *procNameObj, Jim_Cmd *cmd)
+{
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", JimCmdUsage(interp, procNameObj, cmd));
}
#ifdef jim_ext_namespace
return retcode;
}
+static int JimCallNative(Jim_Interp *interp, Jim_Cmd *cmd, int argc, Jim_Obj *const *argv)
+{
+ int argsok = 1;
+ int ret;
+
+
+ if (argc - 1 < cmd->u.native.minargs) {
+ argsok = 0;
+ }
+ else if (cmd->u.native.maxargs >= 0 && argc - 1 > cmd->u.native.maxargs) {
+ argsok = 0;
+ }
+ else if (cmd->u.native.maxargs < -1 && (argc - 1) % -cmd->u.native.maxargs != 0) {
+
+ argsok = 0;
+ }
+ if (argsok) {
+ interp->cmdPrivData = cmd->u.native.privData;
+ ret = cmd->u.native.cmdProc(interp, argc, argv);
+ if (ret != JIM_USAGE) {
+ return ret;
+ }
+
+ }
+
+ //printf("Wrong args for %s, argc=%d, minargs=%d, maxargs=%d\n", Jim_String(argv[0]), argc, cmd->u.native.minargs, cmd->u.native.maxargs);
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", JimCmdUsage(interp, argv[0], cmd));
+ return JIM_ERR;
+}
+
int Jim_EvalSource(Jim_Interp *interp, const char *filename, int lineno, const char *script)
{
int retval;
#include <sys/stat.h>
-static Jim_Obj *JimReadTextFile(Jim_Interp *interp, const char *filename)
+int Jim_EvalFile(Jim_Interp *interp, const char *filename)
{
- jim_stat_t sb;
- int fd;
+ FILE *fp;
char *buf;
+ Jim_Obj *scriptObjPtr;
+ Jim_Obj *filenameObj, *oldFilenameObj;
+ int retcode = JIM_ERR;
int readlen;
+#define READ_BUF_SIZE 256
- if (Jim_Stat(filename, &sb) == -1 || (fd = open(filename, O_RDONLY | O_TEXT, 0666)) < 0) {
+ if ((fp = fopen(filename, "rt")) == NULL) {
Jim_SetResultFormatted(interp, "couldn't read file \"%s\": %s", filename, strerror(errno));
- return NULL;
- }
- buf = Jim_Alloc(sb.st_size + 1);
- readlen = read(fd, buf, sb.st_size);
- close(fd);
- if (readlen < 0) {
- Jim_Free(buf);
- Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
- return NULL;
+ return JIM_ERR;
}
- else {
- Jim_Obj *objPtr;
- buf[readlen] = 0;
+ scriptObjPtr = Jim_NewStringObj(interp, NULL, 0);
- objPtr = Jim_NewStringObjNoAlloc(interp, buf, readlen);
-
- return objPtr;
+ buf = Jim_Alloc(READ_BUF_SIZE);
+ while ((readlen = fread(buf, 1, READ_BUF_SIZE, fp)) > 0) {
+ Jim_AppendString(interp, scriptObjPtr, buf, readlen);
}
-}
-
-
-int Jim_EvalFile(Jim_Interp *interp, const char *filename)
-{
- Jim_Obj *filenameObj;
- Jim_Obj *oldFilenameObj;
- Jim_Obj *scriptObjPtr;
- int retcode;
-
- scriptObjPtr = JimReadTextFile(interp, filename);
- if (!scriptObjPtr) {
- return JIM_ERR;
+ Jim_Free(buf);
+ if (ferror(fp)) {
+ fclose(fp);
+ Jim_SetResultFormatted(interp, "failed to load file \"%s\": %s", filename, strerror(errno));
+ Jim_FreeNewObj(interp, scriptObjPtr);
+ return retcode;
}
+ fclose(fp);
+
filenameObj = Jim_NewStringObj(interp, filename, -1);
Jim_SetSourceInfo(interp, scriptObjPtr, filenameObj, 1);
-
oldFilenameObj = JimPushInterpObj(interp->currentFilenameObj, filenameObj);
retcode = Jim_EvalObj(interp, scriptObjPtr);
struct JimParserCtx parser;
struct ScriptObj *script = Jim_Alloc(sizeof(*script));
ParseTokenList tokenlist;
+ int oldtaint;
ScriptTokenListInit(&tokenlist);
parser.tline);
}
+ oldtaint = interp->taint;
+ interp->taint = objPtr->taint;
+
script->inUse = 1;
script->substFlags = flags;
Jim_FreeIntRep(interp, objPtr);
Jim_SetIntRepPtr(objPtr, script);
objPtr->typePtr = &scriptObjType;
+ interp->taint = oldtaint;
return JIM_OK;
}
return JIM_OK;
}
-void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
+static Jim_Obj *JimJoinCmdArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
Jim_Obj *listObjPtr;
- JimPanic((argc == 0, "Jim_WrongNumArgs() called with argc=0"));
-
listObjPtr = Jim_NewListObj(interp, argv, argc);
- if (msg && *msg) {
- Jim_ListAppendElement(interp, listObjPtr, Jim_NewStringObj(interp, msg, -1));
- }
Jim_IncrRefCount(listObjPtr);
objPtr = Jim_ListJoin(interp, listObjPtr, " ", 1);
Jim_DecrRefCount(interp, listObjPtr);
+ Jim_IncrRefCount(objPtr);
+
+ return objPtr;
+}
+
+void Jim_WrongNumArgs(Jim_Interp *interp, int argc, Jim_Obj *const *argv, const char *msg)
+{
+ Jim_Obj *objPtr = JimJoinCmdArgs(interp, argc, argv);
+ if (*msg) {
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s %s\"", objPtr, msg);
+ }
+ else {
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
+ }
+ Jim_DecrRefCount(interp, objPtr);
+}
+
+int Jim_CalcTaint(int argc, Jim_Obj *const *argv)
+{
+ int taint = 0;
+#ifdef JIM_TAINT
+ int i;
+ for (i = 0; i < argc; i++) {
+ if (argv[i]) {
+ taint |= argv[i]->taint;
+ }
+ }
+#endif
+ return taint;
+}
- Jim_SetResultFormatted(interp, "wrong # args: should be \"%#s\"", objPtr);
+void Jim_SetTaintError(Jim_Interp *interp, int cmdargs, Jim_Obj *const *argv)
+{
+#ifdef JIM_TAINT
+ Jim_Obj *objPtr = JimJoinCmdArgs(interp, cmdargs, argv);
+ Jim_SetResultFormatted(interp, "%#s: tainted data", objPtr);
+ Jim_DecrRefCount(interp, objPtr);
+ Jim_SetGlobalVariableStr(interp, "errorCode", Jim_NewStringObj(interp, "TAINTED", -1));
+#endif
}
typedef void JimHashtableIteratorCallbackType(Jim_Interp *interp, Jim_Obj *listObjPtr,
}
-#define JIM_CMDLIST_COMMANDS 0
-#define JIM_CMDLIST_PROCS 1
-#define JIM_CMDLIST_CHANNELS 2
+#define JIM_CMDLIST_COMMANDS 1
+#define JIM_CMDLIST_PROCS 2
+#define JIM_CMDLIST_ALIASES 4
+#define JIM_CMDLIST_CHANNELS 8
+
+#define JIM_CMDLIST_ALL 0x1000
static void JimCommandMatch(Jim_Interp *interp, Jim_Obj *listObjPtr,
Jim_Obj *keyObj, void *value, Jim_Obj *patternObj, int type)
{
Jim_Cmd *cmdPtr = (Jim_Cmd *)value;
+ int match = 1;
+
+ if ((type & JIM_CMDLIST_PROCS) && !(cmdPtr->flags & JIM_CMD_ISPROC)) {
+
+ return;
+ }
+ if ((type & JIM_CMDLIST_CHANNELS) && !(cmdPtr->flags & JIM_CMD_ISCHANNEL)) {
- if (type == JIM_CMDLIST_PROCS && !cmdPtr->isproc) {
+ return;
+ }
+ if ((type & JIM_CMDLIST_ALIASES) && !(cmdPtr->flags & JIM_CMD_ISALIAS)) {
+
+ return;
+ }
+ if (!(type & JIM_CMDLIST_ALL) && strchr(Jim_String(keyObj), ' ')) {
return;
}
Jim_IncrRefCount(keyObj);
- if (type != JIM_CMDLIST_CHANNELS || Jim_AioFilehandle(interp, keyObj) >= 0) {
- int match = 1;
- if (patternObj) {
- int plen, slen;
- const char *pattern = Jim_GetStringNoQualifier(patternObj, &plen);
- const char *str = Jim_GetStringNoQualifier(keyObj, &slen);
+ if (patternObj) {
+ int plen, slen;
+ const char *pattern = Jim_GetStringNoQualifier(patternObj, &plen);
+ const char *str = Jim_GetStringNoQualifier(keyObj, &slen);
#ifdef JIM_NO_INTROSPECTION
- match = (JimStringCompareUtf8(pattern, plen, str, slen, 0) == 0);
+ match = (JimStringCompareUtf8(pattern, plen, str, slen, 0) == 0);
#else
- match = JimGlobMatch(pattern, plen, str, slen, 0);
+ match = JimGlobMatch(pattern, plen, str, slen, 0);
#endif
- }
- if (match) {
- Jim_ListAppendElement(interp, listObjPtr, keyObj);
- }
+ }
+ if (match) {
+ Jim_ListAppendElement(interp, listObjPtr, keyObj);
}
Jim_DecrRefCount(interp, keyObj);
}
}
-#define JIM_VARLIST_GLOBALS 0
-#define JIM_VARLIST_LOCALS 1
-#define JIM_VARLIST_VARS 2
-#define JIM_VARLIST_MASK 0x000f
+#define JIM_VARLIST_GLOBALS 1
+#define JIM_VARLIST_LOCALS 2
+#define JIM_VARLIST_VARS 4
#define JIM_VARLIST_VALUES 0x1000
{
Jim_VarVal *vv = (Jim_VarVal *)value;
- if ((type & JIM_VARLIST_MASK) != JIM_VARLIST_LOCALS || vv->linkFramePtr == NULL) {
+ if (!(type & JIM_VARLIST_LOCALS) || vv->linkFramePtr == NULL) {
if (patternObj == NULL || Jim_StringMatchObj(interp, patternObj, keyObj, 0)) {
Jim_ListAppendElement(interp, listObjPtr, keyObj);
if (type & JIM_VARLIST_VALUES) {
static Jim_Obj *JimVariablesList(Jim_Interp *interp, Jim_Obj *patternObjPtr, int mode)
{
- if (mode == JIM_VARLIST_LOCALS && interp->framePtr == interp->topFramePtr) {
+ if ((mode & JIM_VARLIST_LOCALS) && interp->framePtr == interp->topFramePtr) {
return interp->emptyObj;
}
else {
- Jim_CallFrame *framePtr = (mode == JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
+ Jim_CallFrame *framePtr = (mode & JIM_VARLIST_GLOBALS) ? interp->topFramePtr : interp->framePtr;
return JimHashtablePatternMatch(interp, &framePtr->vars, patternObjPtr, JimVariablesMatch,
mode);
}
static int Jim_PutsCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "?-nonewline? string");
- return JIM_ERR;
- }
if (argc == 3) {
if (!Jim_CompareStringImmediate(interp, argv[1], "-nonewline")) {
Jim_SetResultString(interp, "The second argument must " "be -nonewline", -1);
double doubleValue, doubleRes = 0;
int i = 2;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "number ?number ... number?");
- return JIM_ERR;
- }
- else if (argc == 2) {
+ if (argc == 2) {
if (Jim_GetWide(interp, argv[1], &wideValue) != JIM_OK) {
if (Jim_GetDouble(interp, argv[1], &doubleValue) != JIM_OK) {
return JIM_ERR;
static int Jim_SetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?newValue?");
- return JIM_ERR;
- }
if (argc == 2) {
Jim_Obj *objPtr;
static int Jim_WhileCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "condition body");
- return JIM_ERR;
- }
-
while (1) {
int boolean = 0, retval;
Jim_Obj *varNamePtr = NULL;
Jim_Obj *stopVarNamePtr = NULL;
- if (argc != 5) {
- Jim_WrongNumArgs(interp, 1, argv, "start test next body");
- return JIM_ERR;
- }
-
if ((retval = Jim_EvalObj(interp, argv[1])) != JIM_OK) {
return retval;
jim_wide incr = 1;
Jim_Obj *bodyObjPtr;
- if (argc < 4 || argc > 6) {
- Jim_WrongNumArgs(interp, 1, argv, "var ?first? limit ?incr? body");
- return JIM_ERR;
- }
-
retval = Jim_GetWideExpr(interp, argv[2], &i);
if (argc > 4 && retval == JIM_OK) {
retval = Jim_GetWideExpr(interp, argv[3], &limit);
else {
objPtr = Jim_NewIntObj(interp, i);
retval = Jim_SetVariable(interp, argv[1], objPtr);
- if (retval != JIM_OK) {
- Jim_FreeNewObj(interp, objPtr);
- }
}
}
}
Jim_Obj *script;
Jim_Obj *resultObj;
- if (argc < 4 || argc % 2 != 0) {
- Jim_WrongNumArgs(interp, 1, argv, "varList list ?varList list ...? script");
- return JIM_ERR;
+ if (argc % 2 != 0) {
+ return JIM_USAGE;
}
script = argv[argc - 1];
numargs = (argc - 1 - 1);
valObj = interp->emptyObj;
}
-
- Jim_IncrRefCount(valObj);
+ // XXX
+ //Jim_IncrRefCount(valObj);
result = Jim_SetVariable(interp, varName, valObj);
- Jim_DecrRefCount(interp, valObj);
+ //Jim_DecrRefCount(interp, valObj);
if (result != JIM_OK) {
goto err;
}
Jim_ListIter iter;
Jim_Obj *resultObj;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "varList list ?varName ...?");
- return JIM_ERR;
- }
-
JimListIterInit(&iter, argv[1]);
for (i = 2; i < argc; i++) {
{
int boolean, retval, current = 1, falsebody = 0;
- if (argc >= 3) {
- while (1) {
+ while (1) {
- if (current >= argc)
- goto err;
- if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
- != JIM_OK)
- return retval;
+ if (current >= argc) {
+ return JIM_USAGE;
+ }
+ if ((retval = Jim_GetBoolFromExpr(interp, argv[current++], &boolean))
+ != JIM_OK)
+ return retval;
- if (current >= argc)
- goto err;
- if (Jim_CompareStringImmediate(interp, argv[current], "then"))
- current++;
+ if (current >= argc) {
+ return JIM_USAGE;
+ }
+ if (Jim_CompareStringImmediate(interp, argv[current], "then"))
+ current++;
- if (current >= argc)
- goto err;
- if (boolean)
- return Jim_EvalObj(interp, argv[current]);
+ if (current >= argc) {
+ return JIM_USAGE;
+ }
+ if (boolean)
+ return Jim_EvalObj(interp, argv[current]);
- if (++current >= argc) {
- Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
- return JIM_OK;
- }
- falsebody = current++;
- if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
+ if (++current >= argc) {
+ Jim_SetResult(interp, Jim_NewEmptyStringObj(interp));
+ return JIM_OK;
+ }
+ falsebody = current++;
+ if (Jim_CompareStringImmediate(interp, argv[falsebody], "else")) {
- if (current != argc - 1)
- goto err;
- return Jim_EvalObj(interp, argv[current]);
+ if (current != argc - 1) {
+ return JIM_USAGE;
}
- else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
- continue;
+ return Jim_EvalObj(interp, argv[current]);
+ }
+ else if (Jim_CompareStringImmediate(interp, argv[falsebody], "elseif"))
+ continue;
- else if (falsebody != argc - 1)
- goto err;
- return Jim_EvalObj(interp, argv[falsebody]);
+ else if (falsebody != argc - 1) {
+ return JIM_USAGE;
}
- return JIM_OK;
+ return Jim_EvalObj(interp, argv[falsebody]);
}
- err:
- Jim_WrongNumArgs(interp, 1, argv, "condition ?then? trueBody ?elseif ...? ?else? falseBody");
- return JIM_ERR;
+ return JIM_OK;
}
Jim_Obj *command = NULL, *scriptObj = NULL, *strObj;
Jim_Obj **caseList;
- if (argc < 3) {
- wrongnumargs:
- Jim_WrongNumArgs(interp, 1, argv, "?options? string "
- "pattern body ... ?default body? or " "{pattern body ?pattern body ...?}");
- return JIM_ERR;
- }
for (opt = 1; opt < argc; ++opt) {
const char *option = Jim_String(argv[opt]);
else if (strncmp(option, "-command", 2) == 0) {
matchOpt = SWITCH_CMD;
if ((argc - opt) < 2)
- goto wrongnumargs;
+ return JIM_USAGE;
command = argv[++opt];
}
else {
return JIM_ERR;
}
if ((argc - opt) < 2)
- goto wrongnumargs;
+ return JIM_USAGE;
}
strObj = argv[opt++];
patCount = argc - opt;
else
caseList = (Jim_Obj **)&argv[opt];
if (patCount == 0 || patCount % 2 != 0)
- goto wrongnumargs;
+ return JIM_USAGE;
for (i = 0; scriptObj == NULL && i < patCount; i += 2) {
Jim_Obj *patObj = caseList[i];
Jim_Obj *objPtr;
int ret;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "list ?index ...?");
- return JIM_ERR;
- }
ret = Jim_ListIndices(interp, argv[1], argv + 2, argc - 2, &objPtr, JIM_NONE);
if (ret < 0) {
ret = JIM_OK;
static int Jim_LlengthCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "list");
- return JIM_ERR;
- }
Jim_SetResultInt(interp, Jim_ListLength(interp, argv[1]));
return JIM_OK;
}
int match_flags = 0;
long stride = 1;
- if (argc < 3) {
- wrongargs:
- Jim_WrongNumArgs(interp, 1, argv,
- "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? ?-stride len? ?-index val? list value");
- return JIM_ERR;
- }
-
for (i = 1; i < argc - 2; i++) {
int option;
break;
case OPT_COMMAND:
if (i >= argc - 2) {
- goto wrongargs;
+ return JIM_USAGE;
}
commandObj = argv[++i];
break;
case OPT_INDEX:
if (i >= argc - 2) {
- goto wrongargs;
+ return JIM_USAGE;
}
indexObj = argv[++i];
break;
case OPT_STRIDE:
if (i >= argc - 2) {
- goto wrongargs;
+ return JIM_USAGE;
}
if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) {
return JIM_ERR;
argc -= i;
if (argc < 2) {
- goto wrongargs;
+ return JIM_USAGE;
}
argv += i;
static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listObjPtr;
- int new_obj = 0;
int i;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
- return JIM_ERR;
- }
listObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!listObjPtr) {
listObjPtr = Jim_NewListObj(interp, NULL, 0);
- new_obj = 1;
}
else if (Jim_IsShared(listObjPtr)) {
listObjPtr = Jim_DuplicateObj(interp, listObjPtr);
- new_obj = 1;
}
for (i = 2; i < argc; i++)
Jim_ListAppendElement(interp, listObjPtr, argv[i]);
if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) {
- if (new_obj)
- Jim_FreeNewObj(interp, listObjPtr);
return JIM_ERR;
}
Jim_SetResult(interp, listObjPtr);
int idx, len;
Jim_Obj *listPtr;
- if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "list index ?element ...?");
- return JIM_ERR;
- }
listPtr = argv[1];
if (Jim_IsShared(listPtr))
listPtr = Jim_DuplicateObj(interp, listPtr);
Jim_Obj *listObj;
Jim_Obj *newListObj;
- if (argc < 4) {
- Jim_WrongNumArgs(interp, 1, argv, "list first last ?element ...?");
- return JIM_ERR;
- }
if (Jim_GetIndex(interp, argv[2], &first) != JIM_OK ||
Jim_GetIndex(interp, argv[3], &last) != JIM_OK) {
return JIM_ERR;
static int Jim_LsetCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "listVar ?index ...? value");
- return JIM_ERR;
- }
- else if (argc == 3) {
+ if (argc == 3) {
if (Jim_SetVariable(interp, argv[1], argv[2]) != JIM_OK)
return JIM_ERR;
struct lsort_info info;
- if (argc < 2) {
-wrongargs:
- Jim_WrongNumArgs(interp, 1, argv, "?options? list");
- return JIM_ERR;
- }
-
info.type = JIM_LSORT_ASCII;
info.order = 1;
info.indexc = 0;
break;
case OPT_STRIDE:
if (i >= argc - 2) {
- goto wrongargs;
+ return JIM_USAGE;
}
if (Jim_GetLong(interp, argv[++i], &stride) != JIM_OK) {
return JIM_ERR;
Jim_Obj *stringObjPtr;
int i;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?value ...?");
- return JIM_ERR;
- }
if (argc == 2) {
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_ERRMSG);
if (!stringObjPtr)
return JIM_ERR;
}
else {
- int new_obj = 0;
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!stringObjPtr) {
stringObjPtr = Jim_NewEmptyStringObj(interp);
- new_obj = 1;
}
else if (Jim_IsShared(stringObjPtr)) {
- new_obj = 1;
stringObjPtr = Jim_DuplicateObj(interp, stringObjPtr);
}
for (i = 2; i < argc; i++) {
Jim_AppendObj(interp, stringObjPtr, argv[i]);
}
if (Jim_SetVariable(interp, argv[1], stringObjPtr) != JIM_OK) {
- if (new_obj) {
- Jim_FreeNewObj(interp, stringObjPtr);
- }
return JIM_ERR;
}
}
{
int rc;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "arg ?arg ...?");
- return JIM_ERR;
- }
-
if (argc == 2) {
rc = Jim_EvalObj(interp, argv[1]);
}
static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc >= 2) {
- int retcode;
- Jim_CallFrame *savedCallFrame, *targetCallFrame;
- const char *str;
-
-
- savedCallFrame = interp->framePtr;
-
-
- str = Jim_String(argv[1]);
- if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
- targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
- argc--;
- argv++;
- }
- else {
- targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
- }
- if (targetCallFrame == NULL) {
- return JIM_ERR;
- }
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv - 1, "?level? command ?arg ...?");
- return JIM_ERR;
- }
-
- interp->framePtr = targetCallFrame;
- if (argc == 2) {
- retcode = Jim_EvalObj(interp, argv[1]);
- }
- else {
- retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
- }
- interp->framePtr = savedCallFrame;
- return retcode;
+ int retcode;
+ Jim_CallFrame *savedCallFrame, *targetCallFrame;
+ const char *str;
+
+
+ savedCallFrame = interp->framePtr;
+
+
+ str = Jim_String(argv[1]);
+ if ((str[0] >= '0' && str[0] <= '9') || str[0] == '#') {
+ targetCallFrame = Jim_GetCallFrameByLevel(interp, argv[1]);
+ argc--;
+ argv++;
}
else {
- Jim_WrongNumArgs(interp, 1, argv, "?level? command ?arg ...?");
+ targetCallFrame = Jim_GetCallFrameByLevel(interp, NULL);
+ }
+ if (targetCallFrame == NULL) {
return JIM_ERR;
}
-}
-
-
-static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
-{
- int retcode;
+ if (argc < 2) {
+ return JIM_USAGE;
+ }
+ interp->framePtr = targetCallFrame;
if (argc == 2) {
- retcode = Jim_EvalExpression(interp, argv[1]);
+ retcode = Jim_EvalObj(interp, argv[1]);
}
-#ifndef JIM_COMPAT
else {
- Jim_WrongNumArgs(interp, 1, argv, "expression");
- retcode = JIM_ERR;
+ retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
}
-#else
- else if (argc > 2) {
+ interp->framePtr = savedCallFrame;
+ return retcode;
+}
+
+
+static int Jim_ExprCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+#ifdef JIM_COMPAT
+ if (argc > 2) {
+ int retcode;
Jim_Obj *objPtr;
objPtr = Jim_ConcatObj(interp, argc - 1, argv + 1);
Jim_IncrRefCount(objPtr);
retcode = Jim_EvalExpression(interp, objPtr);
Jim_DecrRefCount(interp, objPtr);
- }
- else {
- Jim_WrongNumArgs(interp, 1, argv, "expression ?...?");
- return JIM_ERR;
+
+ return retcode;
}
#endif
- return retcode;
+ return Jim_EvalExpression(interp, argv[1]);
}
static int JimBreakContinueHelper(Jim_Interp *interp, int argc, Jim_Obj *const *argv, int retcode)
{
- if (argc != 1 && argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "?level?");
- return JIM_ERR;
- }
if (argc == 2) {
long level;
int ret = Jim_GetLong(interp, argv[1], &level);
}
if (i != argc - 1 && i != argc) {
- Jim_WrongNumArgs(interp, 1, argv,
- "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?");
+ return JIM_USAGE;
}
static int Jim_AliasCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- Jim_Obj *prefixListObj;
-
- if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "newname command ?args ...?");
- return JIM_ERR;
- }
-
- prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2);
+ Jim_Obj *prefixListObj = Jim_NewListObj(interp, argv + 2, argc - 2);
Jim_IncrRefCount(prefixListObj);
Jim_SetResult(interp, argv[1]);
- return Jim_CreateCommandObj(interp, argv[1], JimAliasCmd, prefixListObj, JimAliasCmdDelete);
+ Jim_RegisterCommand(interp, argv[1], JimAliasCmd, JimAliasCmdDelete, NULL, NULL, 0, -1, JIM_CMD_ISALIAS, prefixListObj);
+ return JIM_OK;
}
{
Jim_Cmd *cmd;
- if (argc != 4 && argc != 5) {
- Jim_WrongNumArgs(interp, 1, argv, "name arglist ?statics? body");
- return JIM_ERR;
- }
-
if (argc == 4) {
cmd = JimCreateProcedureCmd(interp, argv[2], NULL, argv[3], NULL);
}
static int Jim_XtraceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "callback");
- return JIM_ERR;
- }
-
if (interp->traceCmdObj) {
Jim_DecrRefCount(interp, interp->traceCmdObj);
interp->traceCmdObj = NULL;
{
int retcode;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
- return JIM_ERR;
- }
-
interp->local++;
retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
}
if (interp->framePtr->localCommands == NULL) {
interp->framePtr->localCommands = Jim_Alloc(sizeof(*interp->framePtr->localCommands));
- Jim_InitStack(interp->framePtr->localCommands);
+ Jim_StackInit(interp->framePtr->localCommands, NULL);
}
Jim_IncrRefCount(cmdNameObj);
Jim_StackPush(interp->framePtr->localCommands, cmdNameObj);
static int Jim_UpcallCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "cmd ?args ...?");
+ int retcode;
+
+ Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
+ if (cmdPtr == NULL || !(cmdPtr->flags & JIM_CMD_ISPROC) || !cmdPtr->prevCmd) {
+ Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
return JIM_ERR;
}
- else {
- int retcode;
-
- Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[1], JIM_ERRMSG);
- if (cmdPtr == NULL || !cmdPtr->isproc || !cmdPtr->prevCmd) {
- Jim_SetResultFormatted(interp, "no previous command: \"%#s\"", argv[1]);
- return JIM_ERR;
- }
- cmdPtr->u.proc.upcall++;
- JimIncrCmdRefCount(cmdPtr);
+ cmdPtr->u.proc.upcall++;
+ JimIncrCmdRefCount(cmdPtr);
- retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
+ retcode = Jim_EvalObjVector(interp, argc - 1, argv + 1);
- cmdPtr->u.proc.upcall--;
- JimDecrCmdRefCount(interp, cmdPtr);
+ cmdPtr->u.proc.upcall--;
+ JimDecrCmdRefCount(interp, cmdPtr);
- return retcode;
- }
+ return retcode;
}
static int Jim_ApplyCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "lambdaExpr ?arg ...?");
+ int ret;
+ Jim_Cmd *cmd;
+ Jim_Obj *argListObjPtr;
+ Jim_Obj *bodyObjPtr;
+ Jim_Obj *nsObj = NULL;
+ Jim_Obj **nargv;
+
+ int len = Jim_ListLength(interp, argv[1]);
+ if (len != 2 && len != 3) {
+ Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]);
return JIM_ERR;
}
- else {
- int ret;
- Jim_Cmd *cmd;
- Jim_Obj *argListObjPtr;
- Jim_Obj *bodyObjPtr;
- Jim_Obj *nsObj = NULL;
- Jim_Obj **nargv;
-
- int len = Jim_ListLength(interp, argv[1]);
- if (len != 2 && len != 3) {
- Jim_SetResultFormatted(interp, "can't interpret \"%#s\" as a lambda expression", argv[1]);
- return JIM_ERR;
- }
- if (len == 3) {
+ if (len == 3) {
#ifdef jim_ext_namespace
- nsObj = Jim_ListGetIndex(interp, argv[1], 2);
+ nsObj = Jim_ListGetIndex(interp, argv[1], 2);
#else
- Jim_SetResultString(interp, "namespaces not enabled", -1);
- return JIM_ERR;
+ Jim_SetResultString(interp, "namespaces not enabled", -1);
+ return JIM_ERR;
#endif
- }
- argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0);
- bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
+ }
+ argListObjPtr = Jim_ListGetIndex(interp, argv[1], 0);
+ bodyObjPtr = Jim_ListGetIndex(interp, argv[1], 1);
- cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
+ cmd = JimCreateProcedureCmd(interp, argListObjPtr, NULL, bodyObjPtr, nsObj);
- if (cmd) {
+ if (cmd) {
- nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
- nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
- Jim_IncrRefCount(nargv[0]);
- memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
- ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
- Jim_DecrRefCount(interp, nargv[0]);
- Jim_Free(nargv);
+ nargv = Jim_Alloc((argc - 2 + 1) * sizeof(*nargv));
+ nargv[0] = Jim_NewStringObj(interp, "apply lambdaExpr", -1);
+ Jim_IncrRefCount(nargv[0]);
+ memcpy(&nargv[1], argv + 2, (argc - 2) * sizeof(*nargv));
+ ret = JimCallProcedure(interp, cmd, argc - 2 + 1, nargv);
+ Jim_DecrRefCount(interp, nargv[0]);
+ Jim_Free(nargv);
- JimDecrCmdRefCount(interp, cmd);
- return ret;
+ JimDecrCmdRefCount(interp, cmd);
+ return ret;
+ }
+ return JIM_ERR;
+}
+
+#ifdef JIM_TAINT
+static int JimTaintVariable(Jim_Interp *interp, Jim_Obj *nameObjPtr, int taint)
+{
+ Jim_Obj *valueObjPtr = Jim_GetVariable(interp, nameObjPtr, JIM_ERRMSG | JIM_UNSHARED);
+
+ if (valueObjPtr == NULL) {
+ return JIM_ERR;
+ }
+
+ if (Jim_IsShared(valueObjPtr)) {
+ valueObjPtr = Jim_DuplicateObj(interp, valueObjPtr);
+ Jim_SetVariable(interp, nameObjPtr, valueObjPtr);
+ }
+
+ if (taint && nameObjPtr->typePtr == &dictSubstObjType) {
+
+ Jim_Obj *objPtr = Jim_GetVariable(interp, nameObjPtr->internalRep.dictSubstValue.varNameObjPtr, JIM_NONE);
+ if (objPtr) {
+ SetStringFromAny(interp, valueObjPtr);
+ valueObjPtr->taint = taint;
+ objPtr->taint |= taint;
}
+ }
+
+
+ SetStringFromAny(interp, valueObjPtr);
+ valueObjPtr->taint = taint;
+
+ //printf("taint of %s is %d\n", valueObjPtr->bytes, valueObjPtr->taint);
+ return JIM_OK;
+}
+
+
+static int Jim_TaintCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ if (argc != 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "varname");
return JIM_ERR;
}
+ return JimTaintVariable(interp, argv[1], 1);
}
+static int Jim_UntaintCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ if (argc != 2) {
+ Jim_WrongNumArgs(interp, 1, argv, "varname");
+ return JIM_ERR;
+ }
+ return JimTaintVariable(interp, argv[1], 0);
+}
+#endif
+
static int Jim_ConcatCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "?level? otherVar localVar ?otherVar localVar ...?");
- return JIM_ERR;
+ return JIM_USAGE;
}
{
int i;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?varName ...?");
- return JIM_ERR;
- }
if (interp->framePtr->level == 0)
return JIM_OK;
static const jim_subcmd_type cmds[OPT_COUNT + 1] = {
JIM_DEF_SUBCMD("bytelength", "string", 1, 1),
JIM_DEF_SUBCMD("byterange", "string first last", 3, 3),
- JIM_DEF_SUBCMD("cat", "?...?", 0, -1),
+ JIM_DEF_SUBCMD("cat", "?string ...?", 0, -1),
JIM_DEF_SUBCMD("compare", "?-nocase? ?-length int? string1 string2", 2, 5),
JIM_DEF_SUBCMD("equal", "?-nocase? ?-length int? string1 string2", 2, 5),
JIM_DEF_SUBCMD("first", "subString string ?index?", 2, 3),
long i, count = 1;
jim_wide start, elapsed;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "script ?count?");
- return JIM_ERR;
- }
if (argc == 3) {
if (Jim_GetLong(interp, argv[2], &count) != JIM_OK)
return JIM_ERR;
}
-static int Jim_TimeRateCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+static int Jim_TimerateCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
long us = 0;
jim_wide start, delta, overhead;
int count;
int n;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "script ?milliseconds?");
- return JIM_ERR;
- }
if (argc == 3) {
if (Jim_GetLong(interp, argv[2], &us) != JIM_OK)
return JIM_ERR;
{
long exitCode = 0;
- if (argc > 2) {
- Jim_WrongNumArgs(interp, 1, argv, "?exitCode?");
- return JIM_ERR;
- }
if (argc == 2) {
if (Jim_GetLong(interp, argv[1], &exitCode) != JIM_OK)
return JIM_ERR;
static int JimCatchTryHelper(Jim_Interp *interp, int istry, int argc, Jim_Obj *const *argv)
{
- static const char * const wrongargs_catchtry[2] = {
- "?-?no?code ... --? script ?resultVarName? ?optionVarName?",
- "?-?no?code ... --? script ?on|trap codes vars script? ... ?finally script?"
- };
int exitCode = 0;
int i;
int sig = 0;
option = Jim_FindByName(arg, jimReturnCodes, jimReturnCodesSize);
}
if (option < 0) {
- goto wrongargs;
+ return JIM_USAGE;
}
if (ignore) {
idx = i;
if (argc - idx < 1) {
-wrongargs:
- Jim_WrongNumArgs(interp, 1, argv, wrongargs_catchtry[istry]);
- return JIM_ERR;
+ return JIM_USAGE;
}
if ((ignore_mask & (1 << JIM_SIGNAL)) == 0) {
else {
exitCode = Jim_EvalObj(interp, argv[idx]);
- interp->errorFlag = 0;
+ interp->hasErrorStackTrace = 0;
}
interp->signal_level -= sig;
case TRY_ON:
case TRY_TRAP:
if (idx + 4 > argc) {
- goto wrongargs;
+ return JIM_USAGE;
}
if (option == TRY_ON) {
ret = JimMatchReturnCodes(interp, argv[idx + 1], exitCode);
if (ret > JIM_OK) {
- goto wrongargs;
+ return JIM_USAGE;
}
}
else if (errorCodeObj) {
int len = Jim_ListLength(interp, argv[idx + 1]);
- int i;
- ret = JIM_OK;
+ if (len > Jim_ListLength(interp, errorCodeObj)) {
- for (i = 0; i < len; i++) {
- Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i);
- Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i);
- if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) {
- ret = -1;
- break;
+ ret = -1;
+ }
+ else {
+ int i;
+ ret = JIM_OK;
+
+ for (i = 0; i < len; i++) {
+ Jim_Obj *matchObj = Jim_ListGetIndex(interp, argv[idx + 1], i);
+ Jim_Obj *objPtr = Jim_ListGetIndex(interp, errorCodeObj, i);
+ if (Jim_StringCompareObj(interp, matchObj, objPtr, 0) != 0) {
+ ret = -1;
+ break;
+ }
}
}
}
break;
case TRY_FINALLY:
if (idx + 2 != argc) {
- goto wrongargs;
+ return JIM_USAGE;
}
finallyScriptObj = argv[idx + 1];
idx += 2;
static int Jim_RenameCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "oldName newName");
- return JIM_ERR;
- }
-
return Jim_RenameCommand(interp, argv[1], argv[2]);
}
}
case OPT_SET:
- return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG);
+ return Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 4, argv[argc - 1], JIM_ERRMSG | JIM_UNSHARED);
case OPT_EXISTS:{
int rc = Jim_DictKeysVector(interp, argv[2], argv + 3, argc - 3, &objPtr, JIM_NONE);
}
case OPT_UNSET:
- if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_NONE) != JIM_OK) {
+ if (Jim_SetDictKeysVector(interp, argv[2], argv + 3, argc - 3, NULL, JIM_UNSHARED) != JIM_OK) {
return JIM_ERR;
}
return JIM_OK;
int flags = JIM_SUBST_FLAG;
Jim_Obj *objPtr;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "?options? string");
- return JIM_ERR;
- }
for (i = 1; i < (argc - 1); i++) {
int option;
return JIM_OK;
}
+
+static int Jim_LsubstCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ if (argc == 3) {
+ if (Jim_CompareStringImmediate(interp, argv[1], "-line")) {
+ return JimListSubstObj(interp, argv[2], JIM_LSUBST_LINE);
+ }
+ return JIM_USAGE;
+ }
+ return JimListSubstObj(interp, argv[1], 0);
+}
+
#ifdef jim_ext_namespace
static int JimIsGlobalNamespace(Jim_Obj *objPtr)
{
static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *objPtr;
- int mode = 0;
+ int mode = 1;
enum {
INFO_ALIAS,
+ INFO_ALIASES,
INFO_ARGS,
INFO_BODY,
INFO_CHANNELS,
INFO_EXISTS,
INFO_FRAME,
INFO_GLOBALS,
+ INFO_HELP,
INFO_HOSTNAME,
INFO_LEVEL,
INFO_LOCALS,
INFO_SOURCE,
INFO_STACKTRACE,
INFO_STATICS,
+ INFO_TAINTED,
+ INFO_USAGE,
INFO_VARS,
INFO_VERSION,
INFO_COUNT
};
static const jim_subcmd_type cmds[INFO_COUNT + 1] = {
JIM_DEF_SUBCMD("alias", "command", 1, 1),
+ JIM_DEF_SUBCMD("aliases", "?-all? ?pattern?", 0, 2),
JIM_DEF_SUBCMD("args", "procname", 1, 1),
JIM_DEF_SUBCMD("body", "procname", 1, 1),
- JIM_DEF_SUBCMD("channels", "?pattern?", 0, 1),
- JIM_DEF_SUBCMD("commands", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("channels", "?-all? ?pattern?", 0, 2),
+ JIM_DEF_SUBCMD("commands", "?-all? ?pattern?", 0, 2),
JIM_DEF_SUBCMD("complete", "script ?missing?", 1, 2),
JIM_DEF_SUBCMD("exists", "varName", 1, 1),
JIM_DEF_SUBCMD("frame", "?levelNum?", 0, 1),
JIM_DEF_SUBCMD("globals", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("help", "command", 1, 1),
JIM_DEF_SUBCMD("hostname", NULL, 0, 0),
JIM_DEF_SUBCMD("level", "?levelNum?", 0, 1),
JIM_DEF_SUBCMD("locals", "?pattern?", 0, 1),
JIM_DEF_SUBCMD("nameofexecutable", NULL, 0, 0),
JIM_DEF_SUBCMD("patchlevel", NULL, 0, 0),
- JIM_DEF_SUBCMD("procs", "?pattern?", 0, 1),
+ JIM_DEF_SUBCMD("procs", "?-all? ?pattern?", 0, 2),
JIM_DEF_SUBCMD("references", NULL, 0, 0),
JIM_DEF_SUBCMD("returncodes", "?code?", 0, 1),
JIM_DEF_SUBCMD("script", "?filename?", 0, 1),
JIM_DEF_SUBCMD("source", "source ?filename line?", 1, 3),
JIM_DEF_SUBCMD("stacktrace", NULL, 0, 0),
JIM_DEF_SUBCMD("statics", "procname", 1, 1),
+ JIM_DEF_SUBCMD("tainted", "value", 1, 1),
+ JIM_DEF_SUBCMD("usage", "command", 1, 1),
JIM_DEF_SUBCMD("vars", "?pattern?", 0, 1),
JIM_DEF_SUBCMD("version", NULL, 0, 0),
{ NULL }
if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
return JIM_ERR;
}
- if (cmdPtr->isproc || cmdPtr->u.native.cmdProc != JimAliasCmd) {
+ if ((cmdPtr->flags & JIM_CMD_ISALIAS) == 0) {
Jim_SetResultFormatted(interp, "command \"%#s\" is not an alias", argv[2]);
return JIM_ERR;
}
return JIM_OK;
}
+ case INFO_TAINTED:
+ if (argc != 3) {
+ Jim_WrongNumArgs(interp, 2, argv, "value");
+ return JIM_ERR;
+ }
+ Jim_SetResultBool(interp, argv[2]->taint != 0);
+ return JIM_OK;
case INFO_CHANNELS:
- mode++;
+ mode <<= 1;
#ifndef jim_ext_aio
Jim_SetResultString(interp, "aio not enabled", -1);
return JIM_ERR;
#endif
+ case INFO_ALIASES:
+ mode <<= 1;
+
case INFO_PROCS:
- mode++;
+ mode <<= 1;
- case INFO_COMMANDS:
+ case INFO_COMMANDS:{
+ int n = 0;
+ if (argc > 2 && Jim_CompareStringImmediate(interp, argv[2], "-all")) {
+ mode |= JIM_CMDLIST_ALL;
+ n++;
+ }
+ if (argc < 2 + n || argc > 3 + n) {
+ Jim_SetResultFormatted(interp, "wrong # args: should be \"info %#s %s\"", argv[1], cmds[option].args);
+ return JIM_ERR;
+ }
#ifdef jim_ext_namespace
if (!nons) {
+
if (Jim_Length(interp->framePtr->nsObj) || (argc == 3 && JimIsGlobalNamespace(argv[2]))) {
return Jim_EvalPrefix(interp, "namespace info", argc - 1, argv + 1);
}
}
#endif
- Jim_SetResult(interp, JimCommandsList(interp, (argc == 3) ? argv[2] : NULL, mode));
+ Jim_SetResult(interp, JimCommandsList(interp, (argc == 3 + n) ? argv[2 + n] : NULL, mode));
return JIM_OK;
+ }
case INFO_VARS:
- mode++;
+ mode <<= 1;
case INFO_LOCALS:
- mode++;
+ mode <<= 1;
case INFO_GLOBALS:
}
return JIM_OK;
+ case INFO_USAGE:
+ case INFO_HELP:{
+ Jim_Cmd *cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG);
+ if (!cmdPtr) {
+ return JIM_ERR;
+ }
+ if (option == INFO_USAGE) {
+ Jim_SetResult(interp, JimCmdUsage(interp, argv[2], cmdPtr));
+ return JIM_OK;
+ }
+ else if ((cmdPtr->flags & JIM_CMD_ISPROC) == 0) {
+ if (cmdPtr->u.native.help) {
+ Jim_SetResultString(interp, cmdPtr->u.native.help, -1);
+ return JIM_OK;
+ }
+ }
+
+ Jim_SetResultFormatted(interp, "No help available for command \"%#s\"", argv[2]);
+ return JIM_OK;
+ }
+
case INFO_BODY:
case INFO_STATICS:
case INFO_ARGS:{
if ((cmdPtr = Jim_GetCommand(interp, argv[2], JIM_ERRMSG)) == NULL) {
return JIM_ERR;
}
- if (!cmdPtr->isproc) {
+ if ((cmdPtr->flags & JIM_CMD_ISPROC) == 0) {
Jim_SetResultFormatted(interp, "command \"%#s\" is not a procedure", argv[2]);
return JIM_ERR;
}
return JIM_OK;
}
- case INFO_VERSION:
- case INFO_PATCHLEVEL:{
- char buf[(JIM_INTEGER_SPACE * 2) + 1];
+ case INFO_PATCHLEVEL:
+
+#ifdef JIM_GITVERSION
+ Jim_SetResultString(interp, JIM_GITVERSION, -1);
+ return JIM_OK;
+#endif
- sprintf(buf, "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100);
- Jim_SetResultString(interp, buf, -1);
+ case INFO_VERSION:{
+ char versionbuf[64];
+ snprintf(versionbuf, sizeof(versionbuf), "%d.%d", JIM_VERSION / 100, JIM_VERSION % 100);
+ Jim_SetResultString(interp, versionbuf, -1);
return JIM_OK;
}
int result = 0;
static const char * const options[] = {
- "-command", "-proc", "-alias", "-var", NULL
+ "-command", "-proc", "-alias", "-channel", "-var", NULL
};
enum
{
- OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_VAR
+ OPT_COMMAND, OPT_PROC, OPT_ALIAS, OPT_CHANNEL, OPT_VAR
};
int option;
objPtr = argv[2];
}
else {
- Jim_WrongNumArgs(interp, 1, argv, "?option? name");
- return JIM_ERR;
+ return JIM_USAGE;
}
if (option == OPT_VAR) {
break;
case OPT_ALIAS:
- result = cmd->isproc == 0 && cmd->u.native.cmdProc == JimAliasCmd;
+ result = (cmd->flags & JIM_CMD_ISALIAS) != 0;
break;
case OPT_PROC:
- result = cmd->isproc;
+ result = (cmd->flags & JIM_CMD_ISPROC) != 0;
+ break;
+
+ case OPT_CHANNEL:
+ result = (cmd->flags & JIM_CMD_ISCHANNEL) != 0;
break;
}
}
int c;
int len;
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "string ?splitChars?");
- return JIM_ERR;
- }
-
str = Jim_GetString(argv[1], &len);
if (len == 0) {
return JIM_OK;
const char *joinStr;
int joinStrLen;
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "list ?joinString?");
- return JIM_ERR;
- }
if (argc == 2) {
joinStr = " ";
{
Jim_Obj *objPtr;
- if (argc < 2) {
- Jim_WrongNumArgs(interp, 1, argv, "formatString ?arg arg ...?");
- return JIM_ERR;
- }
objPtr = Jim_FormatString(interp, argv[1], argc - 2, argv + 2);
if (objPtr == NULL)
return JIM_ERR;
Jim_Obj *listPtr, **outVec;
int outc, i;
- if (argc < 3) {
- Jim_WrongNumArgs(interp, 1, argv, "string format ?varName varName ...?");
- return JIM_ERR;
- }
if (argv[2]->typePtr != &scanFmtStringObjType)
SetScanFmtFromAny(interp, argv[2]);
if (FormatGetError(argv[2]) != 0) {
static int Jim_ErrorCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- if (argc != 2 && argc != 3) {
- Jim_WrongNumArgs(interp, 1, argv, "message ?stacktrace?");
- return JIM_ERR;
- }
Jim_SetResult(interp, argv[1]);
if (argc == 3) {
JimSetStackTrace(interp, argv[2]);
{
Jim_Obj *objPtr;
- if (argc != 4) {
- Jim_WrongNumArgs(interp, 1, argv, "list first last");
- return JIM_ERR;
- }
if ((objPtr = Jim_ListRange(interp, argv[1], argv[2], argv[3])) == NULL)
return JIM_ERR;
Jim_SetResult(interp, objPtr);
jim_wide count;
if (argc < 2 || Jim_GetWideExpr(interp, argv[1], &count) != JIM_OK || count < 0) {
- Jim_WrongNumArgs(interp, 1, argv, "count ?value ...?");
- return JIM_ERR;
+ return JIM_USAGE;
}
if (count == 0 || argc == 2) {
Jim_SetEmptyResult(interp);
return JIM_OK;
}
- if (argc > 3) {
- Jim_WrongNumArgs(interp, 1, argv, "varName ?default?");
- return JIM_ERR;
- }
key = Jim_String(argv[1]);
val = getenv(key);
if (val == NULL) {
static int Jim_SourceCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
- int retval;
+ int retval = Jim_EvalFile(interp, Jim_String(argv[1]));
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "fileName");
- return JIM_ERR;
- }
- retval = Jim_EvalFile(interp, Jim_String(argv[1]));
- if (retval == JIM_RETURN)
- return JIM_OK;
- return retval;
+ return retval == JIM_RETURN ? JIM_OK : retval;
}
Jim_Obj *revObjPtr, **ele;
int len;
- if (argc != 2) {
- Jim_WrongNumArgs(interp, 1, argv, "list");
- return JIM_ERR;
- }
JimListGetElements(interp, argv[1], &len, &ele);
revObjPtr = Jim_NewListObj(interp, NULL, 0);
ListEnsureLength(revObjPtr, len);
int len, i;
Jim_Obj *objPtr;
- if (argc < 2 || argc > 4) {
- Jim_WrongNumArgs(interp, 1, argv, "?start? end ?step?");
- return JIM_ERR;
- }
if (argc == 2) {
if (Jim_GetWideExpr(interp, argv[1], &end) != JIM_OK)
return JIM_ERR;
{
jim_wide min = 0, max = 0, len, maxMul;
- if (argc < 1 || argc > 3) {
- Jim_WrongNumArgs(interp, 1, argv, "?min? max");
- return JIM_ERR;
- }
if (argc == 1) {
max = JIM_WIDE_MAX;
} else if (argc == 2) {
}
}
-static const struct {
+static const struct jim_core_cmd_def_t {
const char *name;
Jim_CmdProc *cmdProc;
+ short minargs;
+ short maxargs;
+ const char *usage;
+ int flags;
} Jim_CoreCommandsTable[] = {
- {"alias", Jim_AliasCoreCommand},
- {"set", Jim_SetCoreCommand},
- {"unset", Jim_UnsetCoreCommand},
- {"puts", Jim_PutsCoreCommand},
- {"+", Jim_AddCoreCommand},
- {"*", Jim_MulCoreCommand},
- {"-", Jim_SubCoreCommand},
- {"/", Jim_DivCoreCommand},
- {"incr", Jim_IncrCoreCommand},
- {"while", Jim_WhileCoreCommand},
- {"loop", Jim_LoopCoreCommand},
- {"for", Jim_ForCoreCommand},
- {"foreach", Jim_ForeachCoreCommand},
- {"lmap", Jim_LmapCoreCommand},
- {"lassign", Jim_LassignCoreCommand},
- {"if", Jim_IfCoreCommand},
- {"switch", Jim_SwitchCoreCommand},
- {"list", Jim_ListCoreCommand},
- {"lindex", Jim_LindexCoreCommand},
- {"lset", Jim_LsetCoreCommand},
- {"lsearch", Jim_LsearchCoreCommand},
- {"llength", Jim_LlengthCoreCommand},
- {"lappend", Jim_LappendCoreCommand},
- {"linsert", Jim_LinsertCoreCommand},
- {"lreplace", Jim_LreplaceCoreCommand},
- {"lsort", Jim_LsortCoreCommand},
- {"append", Jim_AppendCoreCommand},
- {"eval", Jim_EvalCoreCommand},
- {"uplevel", Jim_UplevelCoreCommand},
- {"expr", Jim_ExprCoreCommand},
- {"break", Jim_BreakCoreCommand},
- {"continue", Jim_ContinueCoreCommand},
- {"proc", Jim_ProcCoreCommand},
- {"xtrace", Jim_XtraceCoreCommand},
- {"concat", Jim_ConcatCoreCommand},
- {"return", Jim_ReturnCoreCommand},
- {"upvar", Jim_UpvarCoreCommand},
- {"global", Jim_GlobalCoreCommand},
- {"string", Jim_StringCoreCommand},
- {"time", Jim_TimeCoreCommand},
- {"timerate", Jim_TimeRateCoreCommand},
- {"exit", Jim_ExitCoreCommand},
- {"catch", Jim_CatchCoreCommand},
- {"try", Jim_TryCoreCommand},
+ {"*", Jim_MulCoreCommand, 0, -1, "?number ...?" },
+ {"+", Jim_AddCoreCommand, 0, -1, "?number ...?" },
+ {"-", Jim_SubCoreCommand, 1, -1, "number ?number ...?" },
+ {"/", Jim_DivCoreCommand, 1, -1, "number ?number ...?" },
+ {"alias", Jim_AliasCoreCommand, 2, -1, "newname command ?args ...?" },
+ {"append", Jim_AppendCoreCommand, 1, -1, "varName ?value ...?" },
+ {"apply", Jim_ApplyCoreCommand, 1, -1, "lambdaExpr ?arg ...?" },
+ {"break", Jim_BreakCoreCommand, 0, 1, "?level?" },
+ {"catch", Jim_CatchCoreCommand, 1, -1, "?-?no?code ... --? script ?resultVarName? ?optionVarName?" },
+ {"concat", Jim_ConcatCoreCommand, 0, -1, "?arg ...?" },
+ {"continue", Jim_ContinueCoreCommand, 0, 1, "?level?" },
+ {"dict", Jim_DictCoreCommand, 1, -1, "subcommand ?arg ...?"},
+ {"env", Jim_EnvCoreCommand, 0, 2, "?varName? ?default?" },
+ {"error", Jim_ErrorCoreCommand, 1, 2, "message ?stacktrace?" },
+ {"eval", Jim_EvalCoreCommand, 1, -1, "arg ?arg ...?" },
+ {"exists", Jim_ExistsCoreCommand, 1, 2, "?-command|-proc|-alias|-channel|-var? name" },
+ {"exit", Jim_ExitCoreCommand, 0, 1, "?exitCode?" },
+#ifdef JIM_COMPAT
+ {"expr", Jim_ExprCoreCommand, 1, -1, "expression ?...?" },
+#else
+ {"expr", Jim_ExprCoreCommand, 1, 1, "expression" },
+#endif
+ {"for", Jim_ForCoreCommand, 4, 4, "start test next body" },
+ {"foreach", Jim_ForeachCoreCommand, 3, -1, "varList list ?varList list ...? script" },
+ {"format", Jim_FormatCoreCommand, 1, -1, "formatString ?arg arg ...?" },
+ {"global", Jim_GlobalCoreCommand, 1, -1, "varName ?varName ...?" },
+ {"if", Jim_IfCoreCommand, 2, -1, "condition ?then? trueBody ?elseif ...? ?else? ?falseBody?" },
+ {"incr", Jim_IncrCoreCommand, 1, 2, "varName ?increment?" },
+ {"info", Jim_InfoCoreCommand, 1, -1, "subcommand ?arg ...?"},
+ {"join", Jim_JoinCoreCommand, 1, 2, "list ?joinString?" },
+ {"lappend", Jim_LappendCoreCommand, 1, -1, "varName ?value value ...?" },
+ {"lassign", Jim_LassignCoreCommand, 2, -1, "varList list ?varName ...?" },
+ {"lindex", Jim_LindexCoreCommand, 1, -1, "list ?index ...?" },
+ {"linsert", Jim_LinsertCoreCommand, 2, -1, "list index ?element ...?" },
+ {"list", Jim_ListCoreCommand, 0, -1, "?arg ...?" },
+ {"llength", Jim_LlengthCoreCommand, 1, 1, "list" },
+ {"lmap", Jim_LmapCoreCommand, 3, -1, "varList list ?varList list ...? script" },
+ {"local", Jim_LocalCoreCommand, 1, -1, "cmd ?args ...?" },
+ {"loop", Jim_LoopCoreCommand, 3, 5, "var ?first? limit ?incr? body" },
+ {"lrange", Jim_LrangeCoreCommand, 3, 3, "list first last" },
+ {"lrepeat", Jim_LrepeatCoreCommand, 1, -1, "count ?value ...?" },
+ {"lreplace", Jim_LreplaceCoreCommand, 3, -1, "list first last ?element ...?" },
+ {"lreverse", Jim_LreverseCoreCommand, 1, 1, "list" },
+ {"lsearch", Jim_LsearchCoreCommand, 2, -1, "?-exact|-glob|-regexp|-command 'command'? ?-bool|-inline? ?-not? ?-nocase? ?-all? ?-stride len? ?-index val? list value" },
+ {"lset", Jim_LsetCoreCommand, 2, -1, "listVar ?index ...? value" },
+ {"lsort", Jim_LsortCoreCommand, 1, -1, "?options? list" },
+ {"lsubst", Jim_LsubstCoreCommand, 1, 2, "?-line? string" },
+ {"proc", Jim_ProcCoreCommand, 3, 4, "name arglist ?statics? body" },
+ {"puts", Jim_PutsCoreCommand, 1, 2, "?-nonewline? string" },
+ {"rand", Jim_RandCoreCommand, 0, 2, "?min? ?max?" },
+ {"range", Jim_RangeCoreCommand, 1, 3, "?start? end ?step?" },
+ {"rename", Jim_RenameCoreCommand, 2, 2, "oldName newName" },
+ {"return", Jim_ReturnCoreCommand, 0, -1, "?-code code? ?-errorinfo stacktrace? ?-level level? ?result?" },
+ {"scan", Jim_ScanCoreCommand, 2, -1, "string format ?varName varName ...?" },
+ {"set", Jim_SetCoreCommand, 1, 2, "varName ?newValue?" },
+ {"source", Jim_SourceCoreCommand, 1, 1, "fileName", JIM_CMD_NOTAINT },
+ {"split", Jim_SplitCoreCommand, 1, 2, "string ?splitChars?" },
+ {"stacktrace", Jim_StacktraceCoreCommand, 0, 2, "?firstlevel? ?lastlevel?" },
+ {"string", Jim_StringCoreCommand, 1, -1, "subcommand ?arg ...?" },
+ {"subst", Jim_SubstCoreCommand, 1, 4, "?options? string" },
+ {"switch", Jim_SwitchCoreCommand, 2, -1, "?options? string pattern body ... ?default body? or pattern body ?pattern body ...?" },
+ {"tailcall", Jim_TailcallCoreCommand, 0, -1, "?cmd arg ...?" },
+ {"time", Jim_TimeCoreCommand, 1, 2, "script ?count?" },
+ {"timerate", Jim_TimerateCoreCommand, 1, 2, "script ?milliseconds?" },
+ {"try", Jim_TryCoreCommand, 1, -1, "?-?no?code ... --? script ?on|trap codes vars script? ... ?finally script?" },
+ {"unset", Jim_UnsetCoreCommand, 0, -1, "?-nocomplain? ?--? ?varName ...?"},
+ {"upcall", Jim_UpcallCoreCommand, 1, -1, "cmd ?args ...?" },
+ {"uplevel", Jim_UplevelCoreCommand, 1, -1, "?level? command ?arg ...?" },
+ {"upvar", Jim_UpvarCoreCommand, 2, -1, "?level? otherVar myVar ?otherVar myVar ...?"},
+ {"while", Jim_WhileCoreCommand, 2, 2, "condition body" },
+ {"xtrace", Jim_XtraceCoreCommand, 1, 1, "callback" },
#ifdef JIM_REFERENCES
- {"ref", Jim_RefCoreCommand},
- {"getref", Jim_GetrefCoreCommand},
- {"setref", Jim_SetrefCoreCommand},
- {"finalize", Jim_FinalizeCoreCommand},
- {"collect", Jim_CollectCoreCommand},
-#endif
- {"rename", Jim_RenameCoreCommand},
- {"dict", Jim_DictCoreCommand},
- {"subst", Jim_SubstCoreCommand},
- {"info", Jim_InfoCoreCommand},
- {"exists", Jim_ExistsCoreCommand},
- {"split", Jim_SplitCoreCommand},
- {"join", Jim_JoinCoreCommand},
- {"format", Jim_FormatCoreCommand},
- {"scan", Jim_ScanCoreCommand},
- {"error", Jim_ErrorCoreCommand},
- {"lrange", Jim_LrangeCoreCommand},
- {"lrepeat", Jim_LrepeatCoreCommand},
- {"env", Jim_EnvCoreCommand},
- {"source", Jim_SourceCoreCommand},
- {"lreverse", Jim_LreverseCoreCommand},
- {"range", Jim_RangeCoreCommand},
- {"rand", Jim_RandCoreCommand},
- {"tailcall", Jim_TailcallCoreCommand},
- {"local", Jim_LocalCoreCommand},
- {"upcall", Jim_UpcallCoreCommand},
- {"apply", Jim_ApplyCoreCommand},
- {"stacktrace", Jim_StacktraceCoreCommand},
+ {"collect", Jim_CollectCoreCommand, 0, 0, "" },
+ {"finalize", Jim_FinalizeCoreCommand, 1, 2, "reference ?finalizerProc?" },
+ {"getref", Jim_GetrefCoreCommand, 1, 1, "reference" },
+ {"ref", Jim_RefCoreCommand, 2, 3, "string tag ?finalizer?" },
+ {"setref", Jim_SetrefCoreCommand, 2, 2, "reference newValue" },
+#endif
+#ifdef JIM_TAINT
+ {"taint", Jim_TaintCoreCommand, 1, 1, "varname"},
+ {"untaint", Jim_UntaintCoreCommand, 1, 1, "varname"},
+#endif
{NULL, NULL},
};
void Jim_RegisterCoreCommands(Jim_Interp *interp)
{
- int i = 0;
+ const struct jim_core_cmd_def_t *c;
- while (Jim_CoreCommandsTable[i].name != NULL) {
- Jim_CreateCommand(interp,
- Jim_CoreCommandsTable[i].name, Jim_CoreCommandsTable[i].cmdProc, NULL, NULL);
- i++;
+ for (c = Jim_CoreCommandsTable; c->name; c++) {
+
+ assert(c->usage);
+ Jim_RegisterCmd(interp, c->name, c->usage, c->minargs, c->maxargs, c->cmdProc, NULL, NULL, c->flags);
}
}
int ret = JIM_ERR;
if (ct) {
- if (ct->flags & JIM_MODFLAG_FULLARGV) {
+ if ((ct->flags & JIM_MODFLAG_NOTAINT) && Jim_CheckTaint(interp, JIM_TAINT_ANY)) {
+ ret = JIM_SUBCMD_TAINTED;
+ }
+ else 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_SubCmdArgError(interp, ct, argv[0]);
+ if (ret == JIM_SUBCMD_TAINTED) {
+ Jim_SetTaintError(interp, 2, argv);
+ }
+ else {
+ Jim_SubCmdArgError(interp, ct, argv[0]);
+ }
ret = JIM_ERR;
}
}
return Jim_CallSubCmd(interp, ct, argc, argv);
}
+Jim_Cmd *Jim_RegisterSubCmd(Jim_Interp *interp, const char *cmdname,
+ const jim_subcmd_type *command_table, Jim_DelCmdProc *delProc)
+{
+ return Jim_RegisterCmd(interp, cmdname,
+ "subcommand ?arg ...?",
+ 1, -1,
+ Jim_SubCmdProc,
+ delProc,
+ (void *)command_table,
+ 0);
+}
+
#include <ctype.h>
#include <stdlib.h>
#include <string.h>
step = utf8_tounicode(format, &ch);
}
if (isdigit(ch)) {
- precision = strtoul(format, &end, 10);
+ precision = strtol(format, &end, 10);
format = end;
step = utf8_tounicode(format, &ch);
} else if (ch == '*') {
#define FAIL(R,M) { (R)->err = (M); return (M); }
-#define ISMULT(c) ((c) == '*' || (c) == '+' || (c) == '?' || (c) == '{')
-#define META "^$.[()|?{+*"
+#define META "^$.[()|"
#define HASWIDTH 1
#define SIMPLE 2
#endif
+static int str_is_mult(const char *s)
+{
+ switch (*s) {
+ case '*':
+ case '+':
+ case '?':
+ return 1;
+ case '{':
+ if (isdigit(UCHAR(s[1]))) {
+ return 1;
+ }
+ break;
+ }
+ return 0;
+}
+
static int str_int_len(const int *seq)
{
int n = 0;
return n;
}
+
+static char *reg_expanded_new_pattern(const char *exp)
+{
+
+ char *newexp = strdup(exp);
+ char *d = newexp;
+ const char *s = exp;
+ int escape = 0;
+
+ while (*s) {
+ if (escape) {
+ escape = 0;
+ continue;
+ }
+ else if (*s == '\\') {
+ escape = 1;
+ }
+ else if (strchr(" \t\r\n\f\v", *s)) {
+ s++;
+ continue;
+ }
+ else if (*s == '#') {
+
+ s++;
+ while (*s && *s != '\n') {
+ s++;
+ }
+ continue;
+ }
+ *d++ = *s++;
+ }
+ *d++ = '\0';
+ return newexp;
+}
+
int jim_regcomp(regex_t *preg, const char *exp, int cflags)
{
int scan;
if (exp == NULL)
FAIL(preg, REG_ERR_NULL_ARGUMENT);
+ if (cflags & REG_EXPANDED) {
+ preg->exp = reg_expanded_new_pattern(exp);
+ exp = preg->exp;
+ }
+
preg->cflags = cflags;
preg->regparse = exp;
if (ret == 0)
return 0;
- op = *preg->regparse;
- if (!ISMULT(op)) {
+ if (!str_is_mult(preg->regparse)) {
*flagp = flags;
return(ret);
}
+ op = *preg->regparse;
if (!(flags&HASWIDTH) && op != '?') {
preg->err = REG_ERR_OPERAND_COULD_BE_EMPTY;
return 0;
}
preg->regparse++;
- if (ISMULT(*preg->regparse)) {
+ if (str_is_mult(preg->regparse)) {
preg->err = REG_ERR_NESTED_COUNT;
return 0;
}
case ')':
preg->err = REG_ERR_INTERNAL;
return 0;
- case '?':
- case '+':
- case '*':
- case '{':
- preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
- return 0;
case '\\':
ch = *preg->regparse++;
switch (ch) {
preg->regparse -= n;
+ if (str_is_mult(preg->regparse)) {
+ preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
+ return 0;
+ }
+
ret = regnode(preg, EXACTLY);
- while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
+ while (*preg->regparse && strchr(META, *preg->regparse) == NULL && !str_is_mult(preg->regparse)) {
n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
if (ch == '\\' && preg->regparse[n]) {
if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
}
- if (ISMULT(preg->regparse[n])) {
+ if (str_is_mult(&preg->regparse[n])) {
if (added) {
}
if (*string) {
nextline:
- if (preg->cflags & REG_NEWLINE) {
+ if (preg->cflags & REG_NEWLINE_ANCHOR) {
string = strchr(string, '\n');
if (string) {
static int reg_iseol(regex_t *preg, int ch)
{
- if (preg->cflags & REG_NEWLINE) {
+ if (preg->cflags & REG_NEWLINE_STOP) {
return ch == '\0' || ch == '\n';
}
else {
void jim_regfree(regex_t *preg)
{
+ free(preg->exp);
free(preg->program);
}