aboutsummaryrefslogtreecommitdiff
path: root/autosetup
diff options
context:
space:
mode:
authorSteve Bennett <steveb@workware.net.au>2016-08-27 20:52:43 +1000
committerSteve Bennett <steveb@workware.net.au>2016-08-28 13:01:31 +1000
commit339204cccb2930435552f296fe5b9184ad6836af (patch)
tree2d31436e75cb59ae1dc4442dfa28094d9b1ef193 /autosetup
parent040b3e203807dffc429e1f0f4bbb2af8c2d4f7b3 (diff)
downloadjimtcl-339204cccb2930435552f296fe5b9184ad6836af.zip
jimtcl-339204cccb2930435552f296fe5b9184ad6836af.tar.gz
jimtcl-339204cccb2930435552f296fe5b9184ad6836af.tar.bz2
Update autosetup to v0.6.5
Adds pkg-config support Signed-off-by: Steve Bennett <steveb@workware.net.au>
Diffstat (limited to 'autosetup')
-rwxr-xr-xautosetup/autosetup43
-rw-r--r--autosetup/cc-db.tcl2
-rw-r--r--autosetup/cc-shared.tcl2
-rw-r--r--autosetup/cc.tcl6
-rw-r--r--autosetup/jimsh0.c724
-rw-r--r--autosetup/pkg-config.tcl138
-rw-r--r--autosetup/system.tcl4
-rw-r--r--autosetup/tmake.auto66
-rw-r--r--autosetup/tmake.tcl52
9 files changed, 772 insertions, 265 deletions
diff --git a/autosetup/autosetup b/autosetup/autosetup
index df3317c..84886c2 100755
--- a/autosetup/autosetup
+++ b/autosetup/autosetup
@@ -135,14 +135,22 @@ proc main {argv} {
autosetup_reference [opt-val {manual ref reference}]
}
+ # Allow combining --install and --init
+ set earlyexit 0
+ if {[opt-val install] ne ""} {
+ use install
+ autosetup_install [opt-val install]
+ incr earlyexit
+ }
+
if {[opt-val init] ne ""} {
use init
autosetup_init [opt-val init]
+ incr earlyexit
}
- if {[opt-val install] ne ""} {
- use install
- autosetup_install [opt-val install]
+ if {$earlyexit} {
+ exit 0
}
if {![file exists $autosetup(autodef)]} {
@@ -163,11 +171,13 @@ proc main {argv} {
autosetup_add_dep $autosetup(autodef)
- set cmd [file-normalize $autosetup(exe)]
+ define CONFIGURE_OPTS ""
foreach arg $autosetup(argv) {
- append cmd " [quote-if-needed $arg]"
+ define-append CONFIGURE_OPTS [quote-if-needed $arg]
}
- define AUTOREMAKE $cmd
+ define AUTOREMAKE [file-normalize $autosetup(exe)]
+ define-append AUTOREMAKE [get-define CONFIGURE_OPTS]
+
# Log how we were invoked
configlog "Invoked as: [getenv WRAPPER $::argv0] [quote-argv $autosetup(argv)]"
@@ -400,7 +410,7 @@ proc options-show {} {
#
# If the name:value form is used, the value must be provided with the option (as --name=myvalue).
# If the name:=value form is used, the value is optional and the given value is used as the default
-# if is not provided.
+# if it is not provided.
#
# Undocumented options are also supported by omitting the "=> description.
# These options are not displayed with --help and can be useful for internal options or as aliases.
@@ -461,6 +471,15 @@ proc define {name {value 1}} {
#dputs "$name <= $value"
}
+# @undefine name
+#
+# Undefine the named variable
+#
+proc undefine {name} {
+ unset -nocomplain ::define($name)
+ #dputs "$name <= <undef>"
+}
+
# @define-append name value ...
#
# Appends the given value(s) to the given 'defined' variable.
@@ -548,7 +567,7 @@ proc env-is-set {name} {
# @readfile filename ?default=""?
#
# Return the contents of the file, without the trailing newline.
-# If the doesn't exist or can't be read, returns $default.
+# If the file doesn't exist or can't be read, returns $default.
#
proc readfile {filename {default_value ""}} {
set result $default_value
@@ -1342,7 +1361,7 @@ proc autosetup_init {type} {
# XXX: Use the options-show code to wrap the description
puts [format "%-10s %s" $type $desc]
}
- exit 0
+ return
}
lassign [dict get $::autosetup(inittypes) $type] desc script
@@ -1352,8 +1371,6 @@ proc autosetup_init {type} {
cd $::autosetup(srcdir)
uplevel #0 $script
-
- exit 0
}
proc autosetup_add_init_type {type desc script} {
@@ -1395,7 +1412,7 @@ proc autosetup_install {dir} {
set f [open autosetup/autosetup w]
- set publicmodules $::autosetup(libdir)/default.auto
+ set publicmodules [glob $::autosetup(libdir)/*.auto]
# First the main script, but only up until "CUT HERE"
set in [open $::autosetup(dir)/autosetup]
@@ -1446,8 +1463,6 @@ proc autosetup_install {dir} {
# Now create 'configure' if necessary
autosetup_create_configure
-
- exit 0
}
proc autosetup_create_configure {} {
diff --git a/autosetup/cc-db.tcl b/autosetup/cc-db.tcl
index adaf930..c67fc6e 100644
--- a/autosetup/cc-db.tcl
+++ b/autosetup/cc-db.tcl
@@ -3,7 +3,7 @@
# @synopsis:
#
-# The 'cc-db' module provides a knowledge based of system idiosyncracies
+# The 'cc-db' module provides a knowledge based of system idiosyncrasies
# In general, this module can always be included
use cc
diff --git a/autosetup/cc-shared.tcl b/autosetup/cc-shared.tcl
index 6cfcb50..86e169c 100644
--- a/autosetup/cc-shared.tcl
+++ b/autosetup/cc-shared.tcl
@@ -16,7 +16,7 @@
## SHOBJ_LDFLAGS_R - as above, but all symbols must be resolved
## SH_LINKFLAGS Flags to use linking an executable which will load shared objects
## LD_LIBRARY_PATH Environment variable which specifies path to shared libraries
-## STRIPLIBFLAGS Arguments to strip to strip a dynamic library
+## STRIPLIBFLAGS Arguments to strip a dynamic library
module-options {}
diff --git a/autosetup/cc.tcl b/autosetup/cc.tcl
index bbe7989..ebd9789 100644
--- a/autosetup/cc.tcl
+++ b/autosetup/cc.tcl
@@ -164,7 +164,7 @@ proc cc-check-defines {args} {
# @cc-check-decls name ...
#
# Checks that each given name is either a preprocessor symbol or rvalue
-# such as an enum. Note that the define used for a decl is HAVE_DECL_xxx
+# such as an enum. Note that the define used is HAVE_DECL_xxx
# rather than HAVE_xxx
proc cc-check-decls {args} {
set ret 1
@@ -203,7 +203,7 @@ proc cc-check-members {args} {
# @cc-check-function-in-lib function libs ?otherlibs?
#
-# Checks that the given given function can be found in one of the libs.
+# Checks that the given function can be found in one of the libs.
#
# First checks for no library required, then checks each of the libraries
# in turn.
@@ -287,7 +287,7 @@ proc cc-check-tools {args} {
# For example, when checking for "grep", the path is searched for
# the executable, 'grep', and if found GREP is defined as "grep".
#
-# It the executable is not found, the variable is defined as false.
+# If the executable is not found, the variable is defined as false.
# Returns 1 if all programs were found, or 0 otherwise.
#
proc cc-check-progs {args} {
diff --git a/autosetup/jimsh0.c b/autosetup/jimsh0.c
index 4d6ec32..463c6c3 100644
--- a/autosetup/jimsh0.c
+++ b/autosetup/jimsh0.c
@@ -10,9 +10,9 @@
#define jim_ext_bootstrap
#define jim_ext_aio
#define jim_ext_readdir
-#define jim_ext_glob
#define jim_ext_regexp
#define jim_ext_file
+#define jim_ext_glob
#define jim_ext_exec
#define jim_ext_clock
#define jim_ext_array
@@ -66,7 +66,9 @@ void *dlsym(void *handle, const char *symbol);
char *dlerror(void);
-#define JIM_SPRINTF_DOUBLE_NEEDS_FIX
+#if defined(__MINGW32__)
+ #define JIM_SPRINTF_DOUBLE_NEEDS_FIX
+#endif
#ifdef _MSC_VER
@@ -453,8 +455,6 @@ typedef struct Jim_ObjType {
#define JIM_TYPE_NONE 0
#define JIM_TYPE_REFERENCES 1
-#define JIM_PRIV_FLAG_SHIFT 20
-
typedef struct Jim_CallFrame {
@@ -472,7 +472,6 @@ typedef struct Jim_CallFrame {
Jim_Obj *fileNameObj;
int line;
Jim_Stack *localCommands;
- int tailcall;
struct Jim_Obj *tailcallObj;
struct Jim_Cmd *tailcallCmd;
} Jim_CallFrame;
@@ -739,8 +738,8 @@ JIM_EXPORT void Jim_SetResultFormatted(Jim_Interp *interp, const char *format, .
JIM_EXPORT void Jim_RegisterCoreCommands (Jim_Interp *interp);
JIM_EXPORT int Jim_CreateCommand (Jim_Interp *interp,
- const char *cmdName, Jim_CmdProc cmdProc, void *privData,
- Jim_DelCmdProc delProc);
+ const char *cmdName, Jim_CmdProc *cmdProc, void *privData,
+ Jim_DelCmdProc *delProc);
JIM_EXPORT int Jim_DeleteCommand (Jim_Interp *interp,
const char *cmdName);
JIM_EXPORT int Jim_RenameCommand (Jim_Interp *interp,
@@ -855,8 +854,9 @@ JIM_EXPORT void Jim_WrongNumArgs (Jim_Interp *interp, int argc,
Jim_Obj *const *argv, const char *msg);
JIM_EXPORT int Jim_GetEnum (Jim_Interp *interp, Jim_Obj *objPtr,
const char * const *tablePtr, int *indexPtr, const char *name, int flags);
-JIM_EXPORT int Jim_ScriptIsComplete (const char *s, int len,
- char *stateCharPtr);
+JIM_EXPORT int Jim_ScriptIsComplete(Jim_Interp *interp,
+ Jim_Obj *scriptObj, char *stateCharPtr);
+
JIM_EXPORT int Jim_FindByName(const char *name, const char * const array[], size_t len);
@@ -1039,7 +1039,16 @@ int Jim_bootstrapInit(Jim_Interp *interp)
return Jim_EvalSource(interp, "bootstrap.tcl", 1,
"\n"
"\n"
-"proc package {args} {}\n"
+"proc package {cmd pkg} {\n"
+" if {$cmd eq \"require\"} {\n"
+" foreach path $::auto_path {\n"
+" if {[file exists $path/$pkg.tcl]} {\n"
+" uplevel #0 [list source $path/$pkg.tcl]\n"
+" return\n"
+" }\n"
+" }\n"
+" }\n"
+"}\n"
);
}
int Jim_initjimshInit(Jim_Interp *interp)
@@ -1795,6 +1804,11 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#define JIM_ANSIC
#endif
+#if defined(JIM_SSL)
+#include <openssl/ssl.h>
+#include <openssl/err.h>
+#endif
+
#define AIO_CMD_LEN 32
#define AIO_BUF_LEN 256
@@ -1817,6 +1831,19 @@ int Jim_tclcompatInit(Jim_Interp *interp)
#endif
#endif
+#define JimCheckStreamError(interp, af) af->fops->error(af)
+
+
+struct AioFile;
+
+typedef struct {
+ int (*writer)(struct AioFile *af, const char *buf, int len);
+ int (*reader)(struct AioFile *af, char *buf, int len);
+ const char *(*getline)(struct AioFile *af, char *buf, int len);
+ int (*error)(const struct AioFile *af);
+ const char *(*strerror)(struct AioFile *af);
+ int (*verify)(struct AioFile *af);
+} JimAioFopsType;
typedef struct AioFile
{
@@ -1829,20 +1856,85 @@ typedef struct AioFile
Jim_Obj *wEvent;
Jim_Obj *eEvent;
int addr_family;
+ void *ssl;
+ const JimAioFopsType *fops;
} AioFile;
+static int stdio_writer(struct AioFile *af, const char *buf, int len)
+{
+ return fwrite(buf, 1, len, af->fp);
+}
+
+static int stdio_reader(struct AioFile *af, char *buf, int len)
+{
+ return fread(buf, 1, len, af->fp);
+}
+
+static const char *stdio_getline(struct AioFile *af, char *buf, int len)
+{
+ return fgets(buf, len, af->fp);
+}
+
+static int stdio_error(const AioFile *af)
+{
+ if (!ferror(af->fp)) {
+ return JIM_OK;
+ }
+ clearerr(af->fp);
+
+ if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
+ return JIM_OK;
+ }
+#ifdef ECONNRESET
+ if (errno == ECONNRESET) {
+ return JIM_OK;
+ }
+#endif
+#ifdef ECONNABORTED
+ if (errno != ECONNABORTED) {
+ return JIM_OK;
+ }
+#endif
+ return JIM_ERR;
+}
+
+static const char *stdio_strerror(struct AioFile *af)
+{
+ return strerror(errno);
+}
+
+static const JimAioFopsType stdio_fops = {
+ stdio_writer,
+ stdio_reader,
+ stdio_getline,
+ stdio_error,
+ stdio_strerror,
+ NULL
+};
+
+
static int JimAioSubCmdProc(Jim_Interp *interp, int argc, Jim_Obj *const *argv);
-static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
+static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
const char *hdlfmt, int family, const char *mode);
+static const char *JimAioErrorString(AioFile *af)
+{
+ if (af && af->fops)
+ return af->fops->strerror(af);
+
+ return strerror(errno);
+}
+
static void JimAioSetError(Jim_Interp *interp, Jim_Obj *name)
{
+ AioFile *af = Jim_CmdPrivData(interp);
+
if (name) {
- Jim_SetResultFormatted(interp, "%#s: %s", name, strerror(errno));
+ Jim_SetResultFormatted(interp, "%#s: %s", name, JimAioErrorString(af));
}
else {
- Jim_SetResultString(interp, strerror(errno), -1);
+ Jim_SetResultString(interp, JimAioErrorString(af), -1);
}
}
@@ -1859,6 +1951,12 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
Jim_DeleteFileHandler(interp, af->fp, JIM_EVENT_READABLE | JIM_EVENT_WRITABLE | JIM_EVENT_EXCEPTION);
#endif
+#if defined(JIM_SSL)
+ if (af->ssl != NULL) {
+ SSL_free(af->ssl);
+ }
+#endif
+
if (!(af->openFlags & AIO_KEEPOPEN)) {
fclose(af->fp);
}
@@ -1866,30 +1964,6 @@ static void JimAioDelProc(Jim_Interp *interp, void *privData)
Jim_Free(af);
}
-static int JimCheckStreamError(Jim_Interp *interp, AioFile *af)
-{
- if (!ferror(af->fp)) {
- return JIM_OK;
- }
- clearerr(af->fp);
-
- if (feof(af->fp) || errno == EAGAIN || errno == EINTR) {
- return JIM_OK;
- }
-#ifdef ECONNRESET
- if (errno == ECONNRESET) {
- return JIM_OK;
- }
-#endif
-#ifdef ECONNABORTED
- if (errno != ECONNABORTED) {
- return JIM_OK;
- }
-#endif
- JimAioSetError(interp, af->filename);
- return JIM_ERR;
-}
-
static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
@@ -1925,7 +1999,7 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
else {
readlen = (neededLen > AIO_BUF_LEN ? AIO_BUF_LEN : neededLen);
}
- retval = fread(buf, 1, readlen, af->fp);
+ retval = af->fops->reader(af, buf, readlen);
if (retval > 0) {
Jim_AppendString(interp, objPtr, buf, retval);
if (neededLen != -1) {
@@ -1953,14 +2027,38 @@ static int aio_cmd_read(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_OK;
}
+AioFile *Jim_AioFile(Jim_Interp *interp, Jim_Obj *command)
+{
+ Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
+
+
+ if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
+ return (AioFile *) cmdPtr->u.native.privData;
+ }
+ Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
+ return NULL;
+}
+
+FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
+{
+ AioFile *af;
+
+ af = Jim_AioFile(interp, command);
+ if (af == NULL) {
+ return NULL;
+ }
+
+ return af->fp;
+}
+
static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
jim_wide count = 0;
jim_wide maxlen = JIM_WIDE_MAX;
- FILE *outfh = Jim_AioFilehandle(interp, argv[0]);
+ AioFile *outf = Jim_AioFile(interp, argv[0]);
- if (outfh == NULL) {
+ if (outf == NULL) {
return JIM_ERR;
}
@@ -1971,23 +2069,18 @@ static int aio_cmd_copy(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
while (count < maxlen) {
- int ch = fgetc(af->fp);
+ char ch;
- if (ch == EOF || fputc(ch, outfh) == EOF) {
+ if (af->fops->reader(af, &ch, 1) != 1) {
+ break;
+ }
+ if (outf->fops->writer(outf, &ch, 1) != 1) {
break;
}
count++;
}
- if (ferror(af->fp)) {
- Jim_SetResultFormatted(interp, "error while reading: %s", strerror(errno));
- clearerr(af->fp);
- return JIM_ERR;
- }
-
- if (ferror(outfh)) {
- Jim_SetResultFormatted(interp, "error while writing: %s", strerror(errno));
- clearerr(outfh);
+ if (JimCheckStreamError(interp, af) || JimCheckStreamError(interp, outf)) {
return JIM_ERR;
}
@@ -2008,7 +2101,8 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
objPtr = Jim_NewStringObj(interp, NULL, 0);
while (1) {
buf[AIO_BUF_LEN - 1] = '_';
- if (fgets(buf, AIO_BUF_LEN, af->fp) == NULL)
+
+ if (af->fops->getline(af, buf, AIO_BUF_LEN) == NULL)
break;
if (buf[AIO_BUF_LEN - 1] == '\0' && buf[AIO_BUF_LEN - 2] != '\n') {
@@ -2026,6 +2120,7 @@ static int aio_cmd_gets(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
break;
}
}
+
if (JimCheckStreamError(interp, af)) {
Jim_FreeNewObj(interp, objPtr);
@@ -2070,8 +2165,8 @@ static int aio_cmd_puts(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
wdata = Jim_GetString(strObj, &wlen);
- if (fwrite(wdata, 1, wlen, af->fp) == (unsigned)wlen) {
- if (argc == 2 || putc('\n', af->fp) != EOF) {
+ if (af->fops->writer(af, wdata, wlen) == wlen) {
+ if (argc == 2 || af->fops->writer(af, "\n", 1) == 1) {
return JIM_OK;
}
}
@@ -2205,6 +2300,17 @@ static int aio_cmd_ndelay(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
}
#endif
+#ifdef HAVE_FSYNC
+static int aio_cmd_sync(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
+{
+ AioFile *af = Jim_CmdPrivData(interp);
+
+ fflush(af->fp);
+ fsync(af->fd);
+ return JIM_OK;
+}
+#endif
+
static int aio_cmd_buffering(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
AioFile *af = Jim_CmdPrivData(interp);
@@ -2310,6 +2416,7 @@ static int aio_cmd_onexception(Jim_Interp *interp, int argc, Jim_Obj *const *arg
}
#endif
+
static const jim_subcmd_type aio_command_table[] = {
{ "read",
"?-nonewline? ?len?",
@@ -2398,6 +2505,15 @@ static const jim_subcmd_type aio_command_table[] = {
},
#endif
+#ifdef HAVE_FSYNC
+ { "sync",
+ NULL,
+ aio_cmd_sync,
+ 0,
+ 0,
+
+ },
+#endif
{ "buffering",
"none|line|full",
aio_cmd_buffering,
@@ -2464,21 +2580,28 @@ static int JimAioOpenCommand(Jim_Interp *interp, int argc,
}
}
#endif
- return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode);
+ return JimMakeChannel(interp, NULL, -1, argv[1], "aio.handle%ld", 0, mode) ? JIM_OK : JIM_ERR;
}
-static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
+
+static AioFile *JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filename,
const char *hdlfmt, int family, const char *mode)
{
AioFile *af;
char buf[AIO_CMD_LEN];
int openFlags = 0;
+ snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
+
if (fh) {
- filename = Jim_NewStringObj(interp, hdlfmt, -1);
openFlags = AIO_KEEPOPEN;
}
+ snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
+ if (!filename) {
+ filename = Jim_NewStringObj(interp, buf, -1);
+ }
+
Jim_IncrRefCount(filename);
if (fh == NULL) {
@@ -2498,7 +2621,7 @@ static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filenam
}
#endif
Jim_DecrRefCount(interp, filename);
- return JIM_ERR;
+ return NULL;
}
}
@@ -2515,23 +2638,25 @@ static int JimMakeChannel(Jim_Interp *interp, FILE *fh, int fd, Jim_Obj *filenam
#endif
af->openFlags = openFlags;
af->addr_family = family;
- snprintf(buf, sizeof(buf), hdlfmt, Jim_GetId(interp));
+ af->fops = &stdio_fops;
+ af->ssl = NULL;
+
Jim_CreateCommand(interp, buf, JimAioSubCmdProc, af, JimAioDelProc);
Jim_SetResult(interp, Jim_MakeGlobalNamespaceName(interp, Jim_NewStringObj(interp, buf, -1)));
- return JIM_OK;
+ return af;
}
#if defined(HAVE_PIPE) || (defined(HAVE_SOCKETPAIR) && defined(HAVE_SYS_UN_H))
static int JimMakeChannelPair(Jim_Interp *interp, int p[2], Jim_Obj *filename,
const char *hdlfmt, int family, const char *mode[2])
{
- if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0]) == JIM_OK) {
+ if (JimMakeChannel(interp, NULL, p[0], filename, hdlfmt, family, mode[0])) {
Jim_Obj *objPtr = Jim_NewListObj(interp, NULL, 0);
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
- if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1]) == JIM_OK) {
+ if (JimMakeChannel(interp, NULL, p[1], filename, hdlfmt, family, mode[1])) {
Jim_ListAppendElement(interp, objPtr, Jim_GetResult(interp));
Jim_SetResult(interp, objPtr);
return JIM_OK;
@@ -2569,7 +2694,12 @@ int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
filenameObj = Jim_NewStringObj(interp, template, -1);
}
+#if defined(S_IRWXG) && defined(S_IRWXO)
mask = umask(S_IXUSR | S_IRWXG | S_IRWXO);
+#else
+
+ mask = umask(S_IXUSR);
+#endif
fd = mkstemp(filenameObj->bytes);
@@ -2588,23 +2718,16 @@ int Jim_MakeTempFile(Jim_Interp *interp, const char *template)
#endif
}
-FILE *Jim_AioFilehandle(Jim_Interp *interp, Jim_Obj *command)
-{
- Jim_Cmd *cmdPtr = Jim_GetCommand(interp, command, JIM_ERRMSG);
-
-
- if (cmdPtr && !cmdPtr->isproc && cmdPtr->u.native.cmdProc == JimAioSubCmdProc) {
- return ((AioFile *) cmdPtr->u.native.privData)->fp;
- }
- Jim_SetResultFormatted(interp, "Not a filehandle: \"%#s\"", command);
- return NULL;
-}
int Jim_aioInit(Jim_Interp *interp)
{
if (Jim_PackageProvide(interp, "aio", "1.0", JIM_ERRMSG))
return JIM_ERR;
+#if defined(JIM_SSL)
+ Jim_CreateCommand(interp, "load_ssl_certs", JimAioLoadSSLCertsCommand, NULL, NULL);
+#endif
+
Jim_CreateCommand(interp, "open", JimAioOpenCommand, NULL, NULL);
#ifndef JIM_ANSIC
Jim_CreateCommand(interp, "socket", JimAioSockCommand, NULL, NULL);
@@ -2771,7 +2894,7 @@ int Jim_RegexpCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (argc < 3) {
wrongNumArgs:
Jim_WrongNumArgs(interp, 1, argv,
- "?switches? exp string ?matchVar? ?subMatchVar subMatchVar ...?");
+ "?-switch ...? exp string ?matchVar? ?subMatchVar ...?");
return JIM_ERR;
}
@@ -2993,7 +3116,7 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
if (argc < 4) {
wrongNumArgs:
Jim_WrongNumArgs(interp, 1, argv,
- "?switches? exp string subSpec ?varName?");
+ "?-switch ...? exp string subSpec ?varName?");
return JIM_ERR;
}
@@ -3104,7 +3227,7 @@ int Jim_RegsubCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
continue;
}
else {
- Jim_AppendString(interp, resultObj, replace_str + j - 1, 2);
+ Jim_AppendString(interp, resultObj, replace_str + j - 1, (j == replace_len) ? 1 : 2);
continue;
}
}
@@ -4207,7 +4330,7 @@ static void JimRestoreEnv(char **env);
static int JimCreatePipeline(Jim_Interp *interp, int argc, Jim_Obj *const *argv,
pidtype **pidArrayPtr, fdtype *inPipePtr, fdtype *outPipePtr, fdtype *errFilePtr);
static void JimDetachPids(Jim_Interp *interp, int numPids, const pidtype *pidPtr);
-static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId);
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj);
static fdtype JimCreateTemp(Jim_Interp *interp, const char *contents, int len);
static fdtype JimOpenForWrite(const char *filename, int append);
static int JimRewindFd(fdtype fd);
@@ -4237,22 +4360,24 @@ static int JimAppendStreamToString(Jim_Interp *interp, fdtype fd, Jim_Obj *strOb
{
char buf[256];
FILE *fh = JimFdOpenForRead(fd);
+ int ret = 0;
+
if (fh == NULL) {
- return JIM_ERR;
+ return -1;
}
while (1) {
int retval = fread(buf, 1, sizeof(buf), fh);
if (retval > 0) {
+ ret = 1;
Jim_AppendString(interp, strObj, buf, retval);
}
if (retval != sizeof(buf)) {
break;
}
}
- Jim_RemoveTrailingNewline(strObj);
fclose(fh);
- return JIM_OK;
+ return ret;
}
static char **JimBuildEnv(Jim_Interp *interp)
@@ -4310,21 +4435,34 @@ static void JimFreeEnv(char **env, char **original_environ)
}
}
-static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
+#ifndef jim_ext_signal
+
+const char *Jim_SignalId(int sig)
{
- Jim_Obj *errorCode = Jim_NewListObj(interp, NULL, 0);
- int rc = JIM_ERR;
+ static char buf[10];
+ snprintf(buf, sizeof(buf), "%d", sig);
+ return buf;
+}
+
+const char *Jim_SignalName(int sig)
+{
+ return Jim_SignalId(sig);
+}
+#endif
+
+static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus, Jim_Obj *errStrObj)
+{
+ Jim_Obj *errorCode;
+
+ if (WIFEXITED(waitStatus) && WEXITSTATUS(waitStatus) == 0) {
+ return JIM_OK;
+ }
+ errorCode = Jim_NewListObj(interp, NULL, 0);
if (WIFEXITED(waitStatus)) {
- if (WEXITSTATUS(waitStatus) == 0) {
- Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "NONE", -1));
- rc = JIM_OK;
- }
- else {
- Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
- }
+ Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, "CHILDSTATUS", -1));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WEXITSTATUS(waitStatus)));
}
else {
const char *type;
@@ -4341,20 +4479,17 @@ static int JimCheckWaitStatus(Jim_Interp *interp, pidtype pid, int waitStatus)
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, type, -1));
-#ifdef jim_ext_signal
- Jim_SetResultFormatted(interp, "child %s by signal %s", action, Jim_SignalId(WTERMSIG(waitStatus)));
+ if (errStrObj) {
+ Jim_AppendStrings(interp, errStrObj, "child ", action, " by signal ", Jim_SignalId(WTERMSIG(waitStatus)), "\n", NULL);
+ }
+
+ Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalId(WTERMSIG(waitStatus)), -1));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, pid));
Jim_ListAppendElement(interp, errorCode, Jim_NewStringObj(interp, Jim_SignalName(WTERMSIG(waitStatus)), -1));
-#else
- Jim_SetResultFormatted(interp, "child %s by signal %d", action, WTERMSIG(waitStatus));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, (long)pid));
- Jim_ListAppendElement(interp, errorCode, Jim_NewIntObj(interp, WTERMSIG(waitStatus)));
-#endif
}
Jim_SetGlobalVariableStr(interp, "errorCode", errorCode);
- return rc;
+
+ return JIM_ERR;
}
@@ -4399,6 +4534,9 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
fdtype errorId;
pidtype *pidPtr;
int numPids, result;
+ int child_siginfo = 1;
+ Jim_Obj *childErrObj;
+ Jim_Obj *errStrObj;
if (argc > 1 && Jim_CompareStringImmediate(interp, argv[argc - 1], "&")) {
Jim_Obj *listObj;
@@ -4427,19 +4565,52 @@ static int Jim_ExecCmd(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
return JIM_ERR;
}
- Jim_SetResultString(interp, "", 0);
-
result = JIM_OK;
+
+ errStrObj = Jim_NewStringObj(interp, "", 0);
+
+
if (outputId != JIM_BAD_FD) {
- result = JimAppendStreamToString(interp, outputId, Jim_GetResult(interp));
- if (result < 0) {
+ if (JimAppendStreamToString(interp, outputId, errStrObj) < 0) {
+ result = JIM_ERR;
Jim_SetResultErrno(interp, "error reading from output pipe");
}
}
- if (JimCleanupChildren(interp, numPids, pidPtr, errorId) != JIM_OK) {
+
+ childErrObj = Jim_NewStringObj(interp, "", 0);
+ Jim_IncrRefCount(childErrObj);
+
+ if (JimCleanupChildren(interp, numPids, pidPtr, childErrObj) != JIM_OK) {
result = JIM_ERR;
}
+
+ if (errorId != JIM_BAD_FD) {
+ int ret;
+ JimRewindFd(errorId);
+ ret = JimAppendStreamToString(interp, errorId, errStrObj);
+ if (ret < 0) {
+ Jim_SetResultErrno(interp, "error reading from error pipe");
+ result = JIM_ERR;
+ }
+ else if (ret > 0) {
+
+ child_siginfo = 0;
+ }
+ }
+
+ if (child_siginfo) {
+
+ Jim_AppendObj(interp, errStrObj, childErrObj);
+ }
+ Jim_DecrRefCount(interp, childErrObj);
+
+
+ Jim_RemoveTrailingNewline(errStrObj);
+
+
+ Jim_SetResult(interp, errStrObj);
+
return result;
}
@@ -4936,31 +5107,23 @@ badargs:
}
-static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, fdtype errorId)
+static int JimCleanupChildren(Jim_Interp *interp, int numPids, pidtype *pidPtr, Jim_Obj *errStrObj)
{
struct WaitInfoTable *table = Jim_CmdPrivData(interp);
int result = JIM_OK;
int i;
+
for (i = 0; i < numPids; i++) {
int waitStatus = 0;
if (JimWaitForProcess(table, pidPtr[i], &waitStatus) != JIM_BAD_PID) {
- if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus) != JIM_OK) {
+ if (JimCheckWaitStatus(interp, pidPtr[i], waitStatus, errStrObj) != JIM_OK) {
result = JIM_ERR;
}
}
}
Jim_Free(pidPtr);
- if (errorId != JIM_BAD_FD) {
- JimRewindFd(errorId);
- if (JimAppendStreamToString(interp, errorId, Jim_GetResult(interp)) != JIM_OK) {
- result = JIM_ERR;
- }
- }
-
- Jim_RemoveTrailingNewline(Jim_GetResult(interp));
-
return result;
}
@@ -5197,8 +5360,7 @@ JimWinFindExecutable(const char *originalName, char fullPath[MAX_PATH])
static char extensions[][5] = {".exe", "", ".bat"};
for (i = 0; i < (int) (sizeof(extensions) / sizeof(extensions[0])); i++) {
- lstrcpyn(fullPath, originalName, MAX_PATH - 5);
- lstrcat(fullPath, extensions[i]);
+ snprintf(fullPath, MAX_PATH, "%s%s", originalName, extensions[i]);
if (SearchPath(NULL, fullPath, NULL, MAX_PATH, fullPath, NULL) == 0) {
continue;
@@ -5806,9 +5968,9 @@ int Jim_InitStaticExtensions(Jim_Interp *interp)
extern int Jim_bootstrapInit(Jim_Interp *);
extern int Jim_aioInit(Jim_Interp *);
extern int Jim_readdirInit(Jim_Interp *);
-extern int Jim_globInit(Jim_Interp *);
extern int Jim_regexpInit(Jim_Interp *);
extern int Jim_fileInit(Jim_Interp *);
+extern int Jim_globInit(Jim_Interp *);
extern int Jim_execInit(Jim_Interp *);
extern int Jim_clockInit(Jim_Interp *);
extern int Jim_arrayInit(Jim_Interp *);
@@ -5817,9 +5979,9 @@ extern int Jim_tclcompatInit(Jim_Interp *);
Jim_bootstrapInit(interp);
Jim_aioInit(interp);
Jim_readdirInit(interp);
-Jim_globInit(interp);
Jim_regexpInit(interp);
Jim_fileInit(interp);
+Jim_globInit(interp);
Jim_execInit(interp);
Jim_clockInit(interp);
Jim_arrayInit(interp);
@@ -6819,11 +6981,6 @@ void Jim_FreeStackElements(Jim_Stack *stack, void (*freeFunc) (void *ptr))
#define TOKEN_IS_SEP(type) (type >= JIM_TT_SEP && type <= JIM_TT_EOF)
-
-#define JIM_PS_DEF 0
-#define JIM_PS_QUOTE 1
-#define JIM_PS_DICTSUGAR 2
-
struct JimParseMissing {
int ch;
int line;
@@ -6839,7 +6996,7 @@ struct JimParserCtx
int tline;
int tt;
int eof;
- int state;
+ int inquote;
int comment;
struct JimParseMissing missing;
};
@@ -6866,7 +7023,7 @@ static void JimParserInit(struct JimParserCtx *pc, const char *prg, int len, int
pc->tline = 0;
pc->tt = JIM_TT_NONE;
pc->eof = 0;
- pc->state = JIM_PS_DEF;
+ pc->inquote = 0;
pc->linenr = linenr;
pc->comment = 1;
pc->missing.ch = ' ';
@@ -6886,7 +7043,7 @@ static int JimParseScript(struct JimParserCtx *pc)
}
switch (*(pc->p)) {
case '\\':
- if (*(pc->p + 1) == '\n' && pc->state == JIM_PS_DEF) {
+ if (*(pc->p + 1) == '\n' && !pc->inquote) {
return JimParseSep(pc);
}
pc->comment = 0;
@@ -6895,14 +7052,14 @@ static int JimParseScript(struct JimParserCtx *pc)
case '\t':
case '\r':
case '\f':
- if (pc->state == JIM_PS_DEF)
+ if (!pc->inquote)
return JimParseSep(pc);
pc->comment = 0;
return JimParseStr(pc);
case '\n':
case ';':
pc->comment = 1;
- if (pc->state == JIM_PS_DEF)
+ if (!pc->inquote)
return JimParseEol(pc);
return JimParseStr(pc);
case '[':
@@ -7253,7 +7410,7 @@ static int JimParseStr(struct JimParserCtx *pc)
return JimParseBrace(pc);
}
if (*pc->p == '"') {
- pc->state = JIM_PS_QUOTE;
+ pc->inquote = 1;
pc->p++;
pc->len--;
@@ -7264,7 +7421,7 @@ static int JimParseStr(struct JimParserCtx *pc)
pc->tline = pc->linenr;
while (1) {
if (pc->len == 0) {
- if (pc->state == JIM_PS_QUOTE) {
+ if (pc->inquote) {
pc->missing.ch = '"';
}
pc->tend = pc->p - 1;
@@ -7273,7 +7430,7 @@ static int JimParseStr(struct JimParserCtx *pc)
}
switch (*pc->p) {
case '\\':
- if (pc->state == JIM_PS_DEF && *(pc->p + 1) == '\n') {
+ if (!pc->inquote && *(pc->p + 1) == '\n') {
pc->tend = pc->p - 1;
pc->tt = JIM_TT_ESC;
return JIM_OK;
@@ -7295,6 +7452,7 @@ static int JimParseStr(struct JimParserCtx *pc)
if (pc->len > 1 && pc->p[1] != '$') {
break;
}
+
case ')':
if (*pc->p == '(' || pc->tt == JIM_TT_VAR) {
@@ -7320,7 +7478,7 @@ static int JimParseStr(struct JimParserCtx *pc)
case '\r':
case '\f':
case ';':
- if (pc->state == JIM_PS_DEF) {
+ if (!pc->inquote) {
pc->tend = pc->p - 1;
pc->tt = JIM_TT_ESC;
return JIM_OK;
@@ -7330,12 +7488,12 @@ static int JimParseStr(struct JimParserCtx *pc)
}
break;
case '"':
- if (pc->state == JIM_PS_QUOTE) {
+ if (pc->inquote) {
pc->tend = pc->p - 1;
pc->tt = JIM_TT_ESC;
pc->p++;
pc->len--;
- pc->state = JIM_PS_DEF;
+ pc->inquote = 0;
return JIM_OK;
}
break;
@@ -7396,9 +7554,6 @@ static int JimEscape(char *dest, const char *s, int slen)
char *p = dest;
int i, len;
- if (slen == -1)
- slen = strlen(s);
-
for (i = 0; i < slen; i++) {
switch (s[i]) {
case '\\':
@@ -7577,20 +7732,6 @@ static Jim_Obj *JimParserGetTokenObj(Jim_Interp *interp, struct JimParserCtx *pc
return Jim_NewStringObjNoAlloc(interp, token, len);
}
-int Jim_ScriptIsComplete(const char *s, int len, char *stateCharPtr)
-{
- struct JimParserCtx parser;
-
- JimParserInit(&parser, s, len, 1);
- while (!parser.eof) {
- JimParseScript(&parser);
- }
- if (stateCharPtr) {
- *stateCharPtr = parser.missing.ch;
- }
- return parser.missing.ch == ' ';
-}
-
static int JimParseListSep(struct JimParserCtx *pc);
static int JimParseListStr(struct JimParserCtx *pc);
static int JimParseListQuote(struct JimParserCtx *pc);
@@ -8602,8 +8743,6 @@ static Jim_Obj *JimNewScriptLineObj(Jim_Interp *interp, int argc, int line)
static void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr);
static void DupScriptInternalRep(Jim_Interp *interp, Jim_Obj *srcPtr, Jim_Obj *dupPtr);
-static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
-static int JimParseCheckMissing(Jim_Interp *interp, int ch);
static const Jim_ObjType scriptObjType = {
"script",
@@ -8633,6 +8772,10 @@ typedef struct ScriptObj
int missing;
} ScriptObj;
+static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr);
+static int JimParseCheckMissing(Jim_Interp *interp, int ch);
+static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr);
+
void FreeScriptInternalRep(Jim_Interp *interp, Jim_Obj *objPtr)
{
int i;
@@ -8863,6 +9006,15 @@ static void ScriptObjAddTokens(Jim_Interp *interp, struct ScriptObj *script,
}
+int Jim_ScriptIsComplete(Jim_Interp *interp, Jim_Obj *scriptObj, char *stateCharPtr)
+{
+ ScriptObj *script = JimGetScript(interp, scriptObj);
+ if (stateCharPtr) {
+ *stateCharPtr = script->missing;
+ }
+ return (script->missing == ' ');
+}
+
static int JimParseCheckMissing(Jim_Interp *interp, int ch)
{
const char *msg;
@@ -8963,7 +9115,7 @@ static void JimSetScriptFromAny(Jim_Interp *interp, struct Jim_Obj *objPtr)
static void JimAddErrorToStack(Jim_Interp *interp, ScriptObj *script);
-ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
+static ScriptObj *JimGetScript(Jim_Interp *interp, Jim_Obj *objPtr)
{
if (objPtr == interp->emptyObj) {
@@ -9143,7 +9295,7 @@ static int JimCreateCommand(Jim_Interp *interp, const char *name, Jim_Cmd *cmd)
int Jim_CreateCommand(Jim_Interp *interp, const char *cmdNameStr,
- Jim_CmdProc cmdProc, void *privData, Jim_DelCmdProc delProc)
+ Jim_CmdProc *cmdProc, void *privData, Jim_DelCmdProc *delProc)
{
Jim_Cmd *cmdPtr = Jim_Alloc(sizeof(*cmdPtr));
@@ -10078,7 +10230,6 @@ static Jim_CallFrame *JimCreateCallFrame(Jim_Interp *interp, Jim_CallFrame *pare
cf->next = NULL;
cf->staticVars = NULL;
cf->localCommands = NULL;
- cf->tailcall = 0;
cf->tailcallObj = NULL;
cf->tailcallCmd = NULL;
}
@@ -10485,6 +10636,7 @@ Jim_Interp *Jim_CreateInterp(void)
Jim_SetVariableStrWithStr(i, JIM_LIBPATH, TCL_LIBRARY);
Jim_SetVariableStrWithStr(i, JIM_INTERACTIVE, "0");
+ Jim_SetVariableStrWithStr(i, "tcl_platform(engine)", "Jim");
Jim_SetVariableStrWithStr(i, "tcl_platform(os)", TCL_PLATFORM_OS);
Jim_SetVariableStrWithStr(i, "tcl_platform(platform)", TCL_PLATFORM_PLATFORM);
Jim_SetVariableStrWithStr(i, "tcl_platform(pathSeparator)", TCL_PLATFORM_PATH_SEPARATOR);
@@ -11093,6 +11245,7 @@ static unsigned char ListElementQuotingType(const char *s, int len)
case '\f':
case '\v':
trySimple = 0;
+
case '{':
case '}':
goto testbrace;
@@ -11567,6 +11720,7 @@ static int ListSortElements(Jim_Interp *interp, Jim_Obj *listObjPtr, struct lsor
default:
fn = NULL;
JimPanic((1, "ListSort called with invalid sort type"));
+ return -1;
}
if (info->indexed) {
@@ -15420,31 +15574,27 @@ badargset:
interp->framePtr = interp->framePtr->parent;
JimFreeCallFrame(interp, callFramePtr, JIM_FCF_REUSE);
+
if (interp->framePtr->tailcallObj) {
-
- if (interp->framePtr->tailcall++ == 0) {
-
- do {
- Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
+ do {
+ Jim_Obj *tailcallObj = interp->framePtr->tailcallObj;
- interp->framePtr->tailcallObj = NULL;
+ interp->framePtr->tailcallObj = NULL;
- if (retcode == JIM_EVAL) {
- retcode = Jim_EvalObjList(interp, tailcallObj);
- if (retcode == JIM_RETURN) {
- interp->returnLevel++;
- }
+ if (retcode == JIM_EVAL) {
+ retcode = Jim_EvalObjList(interp, tailcallObj);
+ if (retcode == JIM_RETURN) {
+ interp->returnLevel++;
}
- Jim_DecrRefCount(interp, tailcallObj);
- } while (interp->framePtr->tailcallObj);
-
-
- if (interp->framePtr->tailcallCmd) {
- JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
- interp->framePtr->tailcallCmd = NULL;
}
+ Jim_DecrRefCount(interp, tailcallObj);
+ } while (interp->framePtr->tailcallObj);
+
+
+ if (interp->framePtr->tailcallCmd) {
+ JimDecrCmdRefCount(interp, interp->framePtr->tailcallCmd);
+ interp->framePtr->tailcallCmd = NULL;
}
- interp->framePtr->tailcall--;
}
@@ -16873,7 +17023,8 @@ static int Jim_LsearchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *argv)
{
Jim_Obj *listObjPtr;
- int shared, i;
+ int new_obj = 0;
+ int i;
if (argc < 2) {
Jim_WrongNumArgs(interp, 1, argv, "varName ?value value ...?");
@@ -16883,18 +17034,16 @@ static int Jim_LappendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
if (!listObjPtr) {
listObjPtr = Jim_NewListObj(interp, NULL, 0);
- if (Jim_SetVariable(interp, argv[1], listObjPtr) != JIM_OK) {
- Jim_FreeNewObj(interp, listObjPtr);
- return JIM_ERR;
- }
+ new_obj = 1;
}
- shared = Jim_IsShared(listObjPtr);
- if (shared)
+ 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 (shared)
+ if (new_obj)
Jim_FreeNewObj(interp, listObjPtr);
return JIM_ERR;
}
@@ -17103,22 +17252,22 @@ static int Jim_AppendCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *a
return JIM_ERR;
}
else {
- int freeobj = 0;
+ int new_obj = 0;
stringObjPtr = Jim_GetVariable(interp, argv[1], JIM_UNSHARED);
if (!stringObjPtr) {
stringObjPtr = Jim_NewEmptyStringObj(interp);
- freeobj = 1;
+ new_obj = 1;
}
else if (Jim_IsShared(stringObjPtr)) {
- freeobj = 1;
+ 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 (freeobj) {
+ if (new_obj) {
Jim_FreeNewObj(interp, stringObjPtr);
}
return JIM_ERR;
@@ -17167,7 +17316,6 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
if (argc >= 2) {
int retcode;
Jim_CallFrame *savedCallFrame, *targetCallFrame;
- int savedTailcall;
const char *str;
@@ -17192,16 +17340,12 @@ static int Jim_UplevelCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *
}
interp->framePtr = targetCallFrame;
-
- savedTailcall = interp->framePtr->tailcall;
- interp->framePtr->tailcall = 0;
if (argc == 2) {
retcode = Jim_EvalObj(interp, argv[1]);
}
else {
retcode = Jim_EvalObj(interp, Jim_ConcatObj(interp, argc - 1, argv + 1));
}
- interp->framePtr->tailcall = savedTailcall;
interp->framePtr = savedCallFrame;
return retcode;
}
@@ -18121,10 +18265,10 @@ static int Jim_CatchCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *ar
}
if (ignore) {
- ignore_mask |= (1 << option);
+ ignore_mask |= ((jim_wide)1 << option);
}
else {
- ignore_mask &= ~(1 << option);
+ ignore_mask &= (~((jim_wide)1 << option));
}
}
@@ -18672,8 +18816,10 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
Jim_SetResultString(interp, "aio not enabled", -1);
return JIM_ERR;
#endif
+
case INFO_PROCS:
mode++;
+
case INFO_COMMANDS:
if (argc != 2 && argc != 3) {
@@ -18692,8 +18838,10 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
case INFO_VARS:
mode++;
+
case INFO_LOCALS:
mode++;
+
case INFO_GLOBALS:
if (argc != 2 && argc != 3) {
@@ -18829,11 +18977,9 @@ static int Jim_InfoCoreCommand(Jim_Interp *interp, int argc, Jim_Obj *const *arg
return JIM_ERR;
}
else {
- int len;
- const char *s = Jim_GetString(argv[2], &len);
char missing;
- Jim_SetResultBool(interp, Jim_ScriptIsComplete(s, len, &missing));
+ Jim_SetResultBool(interp, Jim_ScriptIsComplete(interp, argv[2], &missing));
if (missing != ' ' && argc == 4) {
Jim_SetVariable(interp, argv[3], Jim_NewStringObj(interp, &missing, 1));
}
@@ -20292,9 +20438,10 @@ Jim_Obj *Jim_FormatString(Jim_Interp *interp, Jim_Obj *fmtObjPtr, int objc, Jim_
#define REPMIN 11
#define REPX 12
#define REPXMIN 13
-
-#define WORDA 15
-#define WORDZ 16
+#define BOLX 14
+#define EOLX 15
+#define WORDA 16
+#define WORDZ 17
#define OPENNC 1000
#define OPEN 1001
@@ -20799,27 +20946,73 @@ static int regatom(regex_t *preg, int *flagp)
reg_addrange(preg, start, end);
continue;
}
- if (start == '[') {
- if (strncmp(pattern, ":alpha:]", 8) == 0) {
- if ((preg->cflags & REG_ICASE) == 0) {
- reg_addrange(preg, 'a', 'z');
+ if (start == '[' && pattern[0] == ':') {
+ static const char *character_class[] = {
+ ":alpha:", ":alnum:", ":space:", ":blank:", ":upper:", ":lower:",
+ ":digit:", ":xdigit:", ":cntrl:", ":graph:", ":print:", ":punct:",
+ };
+ enum {
+ CC_ALPHA, CC_ALNUM, CC_SPACE, CC_BLANK, CC_UPPER, CC_LOWER,
+ CC_DIGIT, CC_XDIGIT, CC_CNTRL, CC_GRAPH, CC_PRINT, CC_PUNCT,
+ CC_NUM
+ };
+ int i;
+
+ for (i = 0; i < CC_NUM; i++) {
+ int n = strlen(character_class[i]);
+ if (strncmp(pattern, character_class[i], n) == 0) {
+
+ pattern += n + 1;
+ break;
}
- reg_addrange(preg, 'A', 'Z');
- pattern += 8;
- continue;
}
- if (strncmp(pattern, ":alnum:]", 8) == 0) {
- if ((preg->cflags & REG_ICASE) == 0) {
- reg_addrange(preg, 'a', 'z');
+ if (i != CC_NUM) {
+ switch (i) {
+ case CC_ALNUM:
+ reg_addrange(preg, '0', '9');
+
+ case CC_ALPHA:
+ if ((preg->cflags & REG_ICASE) == 0) {
+ reg_addrange(preg, 'a', 'z');
+ }
+ reg_addrange(preg, 'A', 'Z');
+ break;
+ case CC_SPACE:
+ reg_addrange_str(preg, " \t\r\n\f\v");
+ break;
+ case CC_BLANK:
+ reg_addrange_str(preg, " \t");
+ break;
+ case CC_UPPER:
+ reg_addrange(preg, 'A', 'Z');
+ break;
+ case CC_LOWER:
+ reg_addrange(preg, 'a', 'z');
+ break;
+ case CC_XDIGIT:
+ reg_addrange(preg, 'a', 'f');
+ reg_addrange(preg, 'A', 'F');
+
+ case CC_DIGIT:
+ reg_addrange(preg, '0', '9');
+ break;
+ case CC_CNTRL:
+ reg_addrange(preg, 0, 31);
+ reg_addrange(preg, 127, 127);
+ break;
+ case CC_PRINT:
+ reg_addrange(preg, ' ', '~');
+ break;
+ case CC_GRAPH:
+ reg_addrange(preg, '!', '~');
+ break;
+ case CC_PUNCT:
+ reg_addrange(preg, '!', '/');
+ reg_addrange(preg, ':', '@');
+ reg_addrange(preg, '[', '`');
+ reg_addrange(preg, '{', '~');
+ break;
}
- reg_addrange(preg, 'A', 'Z');
- reg_addrange(preg, '0', '9');
- pattern += 8;
- continue;
- }
- if (strncmp(pattern, ":space:]", 8) == 0) {
- reg_addrange_str(preg, " \t\r\n\f\v");
- pattern += 8;
continue;
}
}
@@ -20854,10 +21047,17 @@ static int regatom(regex_t *preg, int *flagp)
preg->err = REG_ERR_COUNT_FOLLOWS_NOTHING;
return 0;
case '\\':
- switch (*preg->regparse++) {
+ ch = *preg->regparse++;
+ switch (ch) {
case '\0':
preg->err = REG_ERR_TRAILING_BACKSLASH;
return 0;
+ case 'A':
+ ret = regnode(preg, BOLX);
+ break;
+ case 'Z':
+ ret = regnode(preg, EOLX);
+ break;
case '<':
case 'm':
ret = regnode(preg, WORDA);
@@ -20867,13 +21067,15 @@ static int regatom(regex_t *preg, int *flagp)
ret = regnode(preg, WORDZ);
break;
case 'd':
- ret = regnode(preg, ANYOF);
+ case 'D':
+ ret = regnode(preg, ch == 'd' ? ANYOF : ANYBUT);
reg_addrange(preg, '0', '9');
regc(preg, '\0');
*flagp |= HASWIDTH|SIMPLE;
break;
case 'w':
- ret = regnode(preg, ANYOF);
+ case 'W':
+ ret = regnode(preg, ch == 'w' ? ANYOF : ANYBUT);
if ((preg->cflags & REG_ICASE) == 0) {
reg_addrange(preg, 'a', 'z');
}
@@ -20884,7 +21086,8 @@ static int regatom(regex_t *preg, int *flagp)
*flagp |= HASWIDTH|SIMPLE;
break;
case 's':
- ret = regnode(preg, ANYOF);
+ case 'S':
+ ret = regnode(preg, ch == 's' ? ANYOF : ANYBUT);
reg_addrange_str(preg," \t\r\n\f\v");
regc(preg, '\0');
*flagp |= HASWIDTH|SIMPLE;
@@ -20911,7 +21114,7 @@ static int regatom(regex_t *preg, int *flagp)
while (*preg->regparse && strchr(META, *preg->regparse) == NULL) {
n = reg_utf8_tounicode_case(preg->regparse, &ch, (preg->cflags & REG_ICASE));
if (ch == '\\' && preg->regparse[n]) {
- if (strchr("<>mMwds", preg->regparse[n])) {
+ if (strchr("<>mMwWdDsSAZ", preg->regparse[n])) {
break;
}
@@ -21341,9 +21544,21 @@ static int regmatch(regex_t *preg, int prog)
n = reg_utf8_tounicode_case(preg->reginput, &c, (preg->cflags & REG_ICASE));
switch (OP(preg, scan)) {
+ case BOLX:
+ if ((preg->eflags & REG_NOTBOL)) {
+ return(0);
+ }
+
case BOL:
- if (preg->reginput != preg->regbol)
+ if (preg->reginput != preg->regbol) {
return(0);
+ }
+ break;
+ case EOLX:
+ if (c != 0) {
+
+ return 0;
+ }
break;
case EOL:
if (!reg_iseol(preg, c)) {
@@ -21731,7 +21946,9 @@ struct dirent *readdir(DIR * dir)
#ifdef USE_LINENOISE
-#include <unistd.h>
+#ifdef HAVE_UNISTD_H
+ #include <unistd.h>
+#endif
#include "linenoise.h"
#else
#define MAX_LINE_LEN 512
@@ -21819,28 +22036,25 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
const char *result;
int reslen;
char prompt[20];
- const char *str;
- if (retcode != 0) {
+ if (retcode != JIM_OK) {
const char *retcodestr = Jim_ReturnCode(retcode);
if (*retcodestr == '?') {
- snprintf(prompt, sizeof(prompt) - 3, "[%d] ", retcode);
+ snprintf(prompt, sizeof(prompt) - 3, "[%d] . ", retcode);
}
else {
- snprintf(prompt, sizeof(prompt) - 3, "[%s] ", retcodestr);
+ snprintf(prompt, sizeof(prompt) - 3, "[%s] . ", retcodestr);
}
}
else {
- prompt[0] = '\0';
+ strcpy(prompt, ". ");
}
- strcat(prompt, ". ");
scriptObjPtr = Jim_NewStringObj(interp, "", 0);
Jim_IncrRefCount(scriptObjPtr);
while (1) {
char state;
- int len;
char *line;
line = Jim_HistoryGetline(prompt);
@@ -21853,21 +22067,18 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
goto out;
}
if (Jim_Length(scriptObjPtr) != 0) {
+
Jim_AppendString(interp, scriptObjPtr, "\n", 1);
}
Jim_AppendString(interp, scriptObjPtr, line, -1);
free(line);
- str = Jim_GetString(scriptObjPtr, &len);
- if (len == 0) {
- continue;
- }
- if (Jim_ScriptIsComplete(str, len, &state))
+ if (Jim_ScriptIsComplete(interp, scriptObjPtr, &state))
break;
snprintf(prompt, sizeof(prompt), "%c> ", state);
}
#ifdef USE_LINENOISE
- if (strcmp(str, "h") == 0) {
+ if (strcmp(Jim_String(scriptObjPtr), "h") == 0) {
Jim_HistoryShow();
Jim_DecrRefCount(interp, scriptObjPtr);
@@ -21883,7 +22094,6 @@ int Jim_InteractivePrompt(Jim_Interp *interp)
Jim_DecrRefCount(interp, scriptObjPtr);
if (retcode == JIM_EXIT) {
- retcode = JIM_EXIT;
break;
}
if (retcode == JIM_ERR) {
@@ -21929,15 +22139,38 @@ static void JimPrintErrorMessage(Jim_Interp *interp)
fprintf(stderr, "%s\n", Jim_String(Jim_GetResult(interp)));
}
+void usage(const char* executable_name)
+{
+ printf("jimsh version %d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
+ printf("Usage: %s\n", executable_name);
+ printf("or : %s [options] [filename]\n", executable_name);
+ printf("\n");
+ printf("Without options: Interactive mode\n");
+ printf("\n");
+ printf("Options:\n");
+ printf(" --version : prints the version string\n");
+ printf(" --help : prints this text\n");
+ printf(" -e CMD : executes command CMD\n");
+ printf(" NOTE: all subsequent options will be passed as arguments to the command\n");
+ printf(" [filename] : executes the script contained in the named file\n");
+ printf(" NOTE: all subsequent options will be passed to the script\n\n");
+}
+
int main(int argc, char *const argv[])
{
int retcode;
Jim_Interp *interp;
+ char *const orig_argv0 = argv[0];
+
if (argc > 1 && strcmp(argv[1], "--version") == 0) {
printf("%d.%d\n", JIM_VERSION / 100, JIM_VERSION % 100);
return 0;
}
+ else if (argc > 1 && strcmp(argv[1], "--help") == 0) {
+ usage(argv[0]);
+ return 0;
+ }
interp = Jim_CreateInterp();
@@ -21948,11 +22181,12 @@ int main(int argc, char *const argv[])
JimPrintErrorMessage(interp);
}
- Jim_SetVariableStrWithStr(interp, "jim::argv0", argv[0]);
+ Jim_SetVariableStrWithStr(interp, "jim::argv0", orig_argv0);
Jim_SetVariableStrWithStr(interp, JIM_INTERACTIVE, argc == 1 ? "1" : "0");
retcode = Jim_initjimshInit(interp);
if (argc == 1) {
+
if (retcode == JIM_ERR) {
JimPrintErrorMessage(interp);
}
@@ -21962,7 +22196,9 @@ int main(int argc, char *const argv[])
}
}
else {
+
if (argc > 2 && strcmp(argv[1], "-e") == 0) {
+
JimSetArgv(interp, argc - 3, argv + 3);
retcode = Jim_Eval(interp, argv[2]);
if (retcode != JIM_ERR) {
diff --git a/autosetup/pkg-config.tcl b/autosetup/pkg-config.tcl
new file mode 100644
index 0000000..c2e2bbf
--- /dev/null
+++ b/autosetup/pkg-config.tcl
@@ -0,0 +1,138 @@
+# Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# @synopsis:
+#
+# The 'pkg-config' module allows package information to be found via pkg-config
+#
+# If not cross-compiling, the package path should be determined automatically
+# by pkg-config.
+# If cross-compiling, the default package path is the compiler sysroot.
+# If the C compiler doesn't support -print-sysroot, the path can be supplied
+# by the --sysroot option or by defining SYSROOT.
+#
+# PKG_CONFIG may be set to use an alternative to pkg-config
+
+use cc
+
+module-options {
+ sysroot:dir => "Override compiler sysroot for pkg-config search path"
+}
+
+# @pkg-config-init ?required?
+#
+# Initialises the pkg-config system. Unless required is set to 0,
+# it is a fatal error if the pkg-config
+# This command will normally be called automatically as required,
+# but it may be invoked explicitly if lack of pkg-config is acceptable.
+#
+# Returns 1 if ok, or 0 if pkg-config not found/usable (only if required=0)
+#
+proc pkg-config-init {{required 1}} {
+ if {[is-defined HAVE_PKG_CONFIG]} {
+ return [get-define HAVE_PKG_CONFIG]
+ }
+ set found 0
+
+ define PKG_CONFIG [get-env PKG_CONFIG pkg-config]
+ msg-checking "Checking for pkg-config..."
+
+ try {
+ set version [exec [get-define PKG_CONFIG] --version]
+ msg-result $version
+ define PKG_CONFIG_VERSION $version
+
+ set found 1
+
+ if {[opt-val sysroot] ne ""} {
+ define SYSROOT [file-normalize [opt-val sysroot]]
+ msg-result "Using specified sysroot [get-define SYSROOT]"
+ } elseif {[get-define build] ne [get-define host]} {
+ if {[catch {exec-with-stderr [get-define CC] -print-sysroot} result errinfo] == 0} {
+ # Use the compiler sysroot, if there is one
+ define SYSROOT $result
+ msg-result "Found compiler sysroot $result"
+ } else {
+ set msg "pkg-config: Cross compiling, but no compiler sysroot and no --sysroot supplied"
+ if {$required} {
+ user-error $msg
+ } else {
+ msg-result $msg
+ }
+ set found 0
+ }
+ }
+ if {[is-defined SYSROOT]} {
+ set sysroot [get-define SYSROOT]
+
+ # XXX: It's possible that these should be set only when invoking pkg-config
+ global env
+ set env(PKG_CONFIG_DIR) ""
+ # Do we need to try /usr/local as well or instead?
+ set env(PKG_CONFIG_LIBDIR) $sysroot/usr/lib/pkgconfig:$sysroot/usr/share/pkgconfig
+ set env(PKG_CONFIG_SYSROOT_DIR) $sysroot
+ }
+
+ } on error msg {
+ msg-result "[get-define PKG_CONFIG] (not found)"
+ if {$required} {
+ user-error "No usable pkg-config"
+ }
+ }
+ define HAVE_PKG_CONFIG $found
+ return $found
+}
+
+# @pkg-config module ?requirements?
+#
+# Use pkg-config to find the given module meeting the given requirements.
+# e.g.
+#
+## pkg-config pango >= 1.37.0
+#
+# If found, returns 1 and sets HAVE_PKG_PANGO to 1 along with:
+#
+## PKG_PANGO_VERSION to the found version
+## PKG_PANGO_LIBS to the required libs (--libs-only-l)
+## PKG_PANGO_LDFLAGS to the required linker flags (--libs-only-L)
+## PKG_PANGO_CFLAGS to the required compiler flags (--cflags)
+#
+# If not found, returns 0.
+#
+proc pkg-config {module args} {
+ set ok [pkg-config-init]
+
+ msg-checking "Checking for $module $args..."
+
+ if {!$ok} {
+ msg-result "no pkg-config"
+ return 0
+ }
+
+ try {
+ set version [exec [get-define PKG_CONFIG] --modversion "$module $args"]
+ msg-result $version
+ set prefix [feature-define-name $module PKG_]
+ define HAVE_${prefix}
+ define ${prefix}_VERSION $version
+ define ${prefix}_LIBS [exec pkg-config --libs-only-l $module]
+ define ${prefix}_LDFLAGS [exec pkg-config --libs-only-L $module]
+ define ${prefix}_CFLAGS [exec pkg-config --cflags $module]
+ return 1
+ } on error msg {
+ msg-result "not found"
+ configlog "pkg-config --modversion $module $args: $msg"
+ return 0
+ }
+}
+
+# @pkg-config-get module setting
+#
+# Convenience access to the results of pkg-config
+#
+# For example, [pkg-config-get pango CFLAGS] returns
+# the value of PKG_PANGO_CFLAGS, or "" if not defined.
+proc pkg-config-get {module name} {
+ set prefix [feature-define-name $module PKG_]
+ get-define ${prefix}_${name} ""
+}
diff --git a/autosetup/system.tcl b/autosetup/system.tcl
index 0166616..9d9cb39 100644
--- a/autosetup/system.tcl
+++ b/autosetup/system.tcl
@@ -4,7 +4,7 @@
# @synopsis:
#
# This module supports common system interrogation and options
-# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEXT.
+# such as --host, --build, --prefix, and setting srcdir, builddir, and EXEEXT
#
# It also support the 'feature' naming convention, where searching
# for a feature such as sys/type.h defines HAVE_SYS_TYPES_H
@@ -106,7 +106,7 @@ proc write-if-changed {file buf {script {}}} {
# If $outfile is blank/omitted, $template should end with ".in" which
# is removed to create the output file name.
#
-# Each pattern of the form @define@ is replaced the the corresponding
+# Each pattern of the form @define@ is replaced with the corresponding
# define, if it exists, or left unchanged if not.
#
# The special value @srcdir@ is substituted with the relative
diff --git a/autosetup/tmake.auto b/autosetup/tmake.auto
new file mode 100644
index 0000000..75813c3
--- /dev/null
+++ b/autosetup/tmake.auto
@@ -0,0 +1,66 @@
+# Copyright (c) 2016 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# Auto-load module for 'tmake' build system integration
+
+use init
+
+autosetup_add_init_type tmake "Tcl-based tmake build system" {
+ autosetup_check_create auto.def \
+{# Initial auto.def created by 'autosetup --init=tmake'
+# vim:set syntax=tcl:
+
+use cc cc-lib cc-db cc-shared
+use tmake
+
+# Add any user options here
+# Really want a --configure that takes over the rest of the command line
+options {
+}
+
+cc-check-tools ar ranlib
+
+set objdir [get-env BUILDDIR objdir]
+
+make-config-header $objdir/include/autoconf.h
+make-tmake-settings $objdir/settings.conf {[A-Z]*}
+}
+
+ autosetup_check_create project.spec \
+{# Initial project.spec created by 'autosetup --init=tmake'
+
+# vim:set syntax=tcl:
+define? DESTDIR _install
+
+# XXX If configure creates additional/different files than include/autoconf.h
+# that should be reflected here
+
+# We use [set AUTOREMAKE] here to avoid rebuilding settings.conf
+# if the AUTOREMAKE command changes
+Depends {settings.conf include/autoconf.h} auto.def -msg {note Configuring...} -do {
+ run [set AUTOREMAKE] >$build/config.out
+} -onerror {puts [readfile $build/config.out]} -fatal
+Clean config.out
+DistClean --source config.log
+DistClean settings.conf include/autoconf.h
+
+# If not configured, configure with default options
+# Note that it is expected that configure will normally be run
+# separately. This is just a convenience for a host build
+define? AUTOREMAKE configure TOPBUILDDIR=$TOPBUILDDIR --conf=auto.def
+
+Load settings.conf
+
+# e.g. for up autoconf.h
+IncludePaths include
+
+ifconfig CONFIGURED
+
+# Hmmm, but should we turn off AutoSubDirs?
+#AutoSubDirs off
+}
+
+ if {![file exists build.spec]} {
+ puts "Note: I don't see build.spec. Try running: tmake --genie"
+ }
+}
diff --git a/autosetup/tmake.tcl b/autosetup/tmake.tcl
new file mode 100644
index 0000000..b946362
--- /dev/null
+++ b/autosetup/tmake.tcl
@@ -0,0 +1,52 @@
+# Copyright (c) 2011 WorkWare Systems http://www.workware.net.au/
+# All rights reserved
+
+# @synopsis:
+#
+# The 'tmake' module makes it easy to support the tmake build system.
+#
+# The following variables are set:
+#
+## CONFIGURED - to indicate that the project is configured
+
+use system
+
+module-options {}
+
+define CONFIGURED
+
+# @make-tmake-settings outfile patterns ...
+#
+# Examines all defined variables which match the given patterns (defaults to "*")
+# and writes a tmake-compatible .conf file defining those variables.
+# For example, if ABC is "3 monkeys" and ABC matches a pattern, then the file will include:
+#
+## define ABC {3 monkeys}
+#
+# If the file would be unchanged, it is not written.
+#
+# Typical usage is:
+#
+# make-tmake-settings [get-env BUILDDIR objdir]/settings.conf {[A-Z]*}
+proc make-tmake-settings {file args} {
+ file mkdir [file dirname $file]
+ set lines {}
+
+ if {[llength $args] == 0} {
+ set args *
+ }
+
+ foreach n [lsort [dict keys [all-defines]]] {
+ foreach p $args {
+ if {[string match $p $n]} {
+ set value [get-define $n]
+ lappend lines "define $n [list $value]"
+ break
+ }
+ }
+ }
+ set buf [join $lines \n]
+ write-if-changed $file $buf {
+ msg-result "Created $file"
+ }
+}