summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog17
-rw-r--r--doc/SubstObj.371
-rw-r--r--doc/subst.n44
-rw-r--r--generic/tcl.decls6
-rw-r--r--generic/tcl.h11
-rw-r--r--generic/tclCmdMZ.c213
-rw-r--r--generic/tclDecls.h10
-rw-r--r--generic/tclStubInit.c3
-rw-r--r--tests/subst.test16
-rw-r--r--unix/mkLinks8
10 files changed, 309 insertions, 90 deletions
diff --git a/ChangeLog b/ChangeLog
index d48e39c..140e139 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,20 @@
+2001-07-12 Donal K. Fellows <fellowsd@cs.man.ac.uk>
+
+ * tests/subst.test (subst-10.*): Updated tests to check new
+ behaviour for 'break' in command substitutions.
+ (subst-1.2,subst-7.1): Error messages changed.
+ * doc/SubstObj.3: New file, to document Tcl_SubstObj.
+ * doc/subst.n: Improved and updated documentation for 'subst' to
+ help support the changed behaviour.
+ * generic/tcl.decls (generic-437): Declaration for Tcl_SubstObj
+ * generic/tcl.h (TCL_SUBST_*): Added flags for Tcl_SubstObj.
+ * generic/tclCmdMZ.c (Tcl_SubstObj,Tcl_SubstObjCmd): Divided into
+ two parts to allow people to access the innards of 'subst' and
+ changed the behaviour when command substitutions do a 'break' to
+ be different from 'continue'. Also now works with objects, which
+ allows for some nifty optimisations with variable substitutions
+ and a slight improvement with command substitutions. [TIP#36]
+
2001-07-10 Mo DeJong <mdejong@redhat.com>
* unix/Makefile.in: Add AR variable for use in STLIB_LD.
diff --git a/doc/SubstObj.3 b/doc/SubstObj.3
new file mode 100644
index 0000000..c90cbca
--- /dev/null
+++ b/doc/SubstObj.3
@@ -0,0 +1,71 @@
+'\"
+'\" Copyright (c) 2001 Donal K. Fellows
+'\"
+'\" See the file "license.terms" for information on usage and redistribution
+'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
+'\"
+'\" RCS: @(#) $Id: SubstObj.3,v 1.1 2001/07/12 13:15:09 dkf Exp $
+'\"
+.so man.macros
+.TH Tcl_SubstObj 3 8.4 Tcl "Tcl Library Procedures"
+.BS
+.SH NAME
+Tcl_SubstObj \- perform substitutions on Tcl objects
+.SH SYNOPSIS
+.nf
+\fB#include <tcl.h>\fR
+.sp
+Tcl_Obj *
+\fBTcl_SubstObj\fR(\fIinterp, objPtr, flags\fR)
+.SH ARGUMENTS
+.AS Tcl_Interp **termPtr;
+.AP Tcl_Interp *interp in
+Interpreter in which to execute Tcl scripts and lookup variables. If
+an error occurs, the interpreter's result is modified to hold an error
+message.
+.AP Tcl_Obj *objPtr in
+A Tcl object containing the string to perform substitutions on.
+.AP int flags in
+ORed combination of flag bits that specify which substitutions to
+perform. The flags \fBTCL_SUBST_COMMANDS\fR,
+\fBTCL_SUBST_VARIABLES\fR and \fBTCL_SUBST_BACKSLASHES\fR are
+currently supported, and \fBTCL_SUBST_ALL\fR is provided as a
+convenience for the common case where all substitutions are desired.
+.BE
+
+.SH DESCRIPTION
+.PP
+The \fBTcl_SubstObj\fR function is used to perform substitutions on
+strings in the fashion of the \fBsubst\fR command. It gets the value
+of the string contained in \fIobjPtr\fR and scans it, copying
+characters and performing the chosen substitutions as it goes to an
+output object which is returned as the result of the function. In the
+event of an error occurring during the execution of a command or
+variable substitution, the function returns NULL and an error message
+is left in \fIinterp\fR's result.
+.PP
+Three kinds of substitutions are supported. When the
+\fBTCL_SUBST_BACKSLASHES\fR bit is set in \fIflags\fR, sequences that
+look like backslash substitutions for Tcl commands are replaced by
+their corresponding character.
+.PP
+When the \fBTCL_SUBST_VARIABLES\fR bit is set in \fIflags\fR,
+sequences that look like variable substitutions for Tcl commands are
+replaced by the contents of the named variable.
+.PP
+When th \fBTCL_SUBST_COMMANDS\fR bit is set in \fIflags\fR, sequences
+that look like command substitutions for Tcl commands are replaced by
+the result of evaluating that script. Where an uncaught continue
+exception occurs during the evaluation of a command substitution, an
+empty string is substituted for the command. Where an uncaught break
+exception occurs during the evaluation of a command substitution, the
+result of the whole substitution on \fIobjPtr\fR will be truncated at
+the point immediately before the start of the command substitution,
+and no characters will be added to the result or substitutions
+performed after that point.
+
+.SH "SEE ALSO"
+subst(n)
+
+.SH KEYWORDS
+backslash substitution, command substitution, variable substitution
diff --git a/doc/subst.n b/doc/subst.n
index 36884eb..b76a70c 100644
--- a/doc/subst.n
+++ b/doc/subst.n
@@ -1,11 +1,12 @@
'\"
'\" Copyright (c) 1994 The Regents of the University of California.
'\" Copyright (c) 1994-1996 Sun Microsystems, Inc.
+'\" Copyright (c) 2001 Donal K. Fellows
'\"
'\" See the file "license.terms" for information on usage and redistribution
'\" of this file, and for a DISCLAIMER OF ALL WARRANTIES.
'\"
-'\" RCS: @(#) $Id: subst.n,v 1.3 2000/09/07 14:27:51 poenitz Exp $
+'\" RCS: @(#) $Id: subst.n,v 1.4 2001/07/12 13:15:09 dkf Exp $
'\"
.so man.macros
.TH subst n 7.4 Tcl "Tcl Built-In Commands"
@@ -35,17 +36,48 @@ For example, if \fB\-nocommands\fR is specified, no command substitution
is performed: open and close brackets are treated as ordinary characters
with no special interpretation.
.PP
-Note: when it performs its substitutions, \fIsubst\fR does not
-give any special treatment to double quotes or curly braces. For
-example, the script
+.VS 8.4
+If a break exception occurs during the evaluation of a command
+substitution, the result of the substitution will be the string (as
+substituted) up to the start of the command substitution. If a
+continue exception occurs during the evaluation of a command
+substitution, an empty string will be substituted for that entire
+command substitution (as long as it is well-formed Tcl.)
+.VE
+.SH EXAMPLES
+.PP
+When it performs its substitutions, \fIsubst\fR does not give any
+special treatment to double quotes or curly braces (except within
+command substitutions) so the script
.CS
\fBset a 44
subst {xyz {$a}}\fR
.CE
-returns ``\fBxyz {44}\fR'', not ``\fBxyz {$a}\fR''.
+returns ``\fBxyz {44}\fR'', not ``\fBxyz {$a}\fR''
+.VS 8.4
+and the script
+.CS
+\fBset a "p\\} q \\{r"
+subst {xyz {$a}}\fR
+.CE
+return ``\fBxyz {p} q {r}\fR'', not ``\fBxyz {p\\} q \\{r}\fR''.
+.PP
+The continue and break exceptions allow command substitutions to
+prevent substitution of the rest of the command substitution and the
+rest of \fIstring\fR respectively, giving script authors more options
+when processing text using \fIsubst\fR. For example, the script
+.CS
+\fBsubst {abc,[break],def}\fR
+.CE
+returns ``\fBabc,\fR'', not ``\fBabc,,def\fR'' and the script
+.CS
+\fBsubst {abc,[continue;expr 1+2],def}\fR
+.CE
+returns ``\fBabc,,def\fR'', not ``\fBabc,3,def\fR''.
+.VE
.SH "SEE ALSO"
-eval(n)
+Tcl(n), eval(n), break(n), continue(n)
.SH KEYWORDS
backslash substitution, command substitution, variable substitution
diff --git a/generic/tcl.decls b/generic/tcl.decls
index f60a719..679cff8 100644
--- a/generic/tcl.decls
+++ b/generic/tcl.decls
@@ -10,7 +10,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: tcl.decls,v 1.49 2001/06/08 20:06:11 dgp Exp $
+# RCS: @(#) $Id: tcl.decls,v 1.50 2001/07/12 13:15:09 dkf Exp $
library tcl
@@ -1527,7 +1527,9 @@ declare 435 generic {
declare 436 generic {
Tcl_Obj * Tcl_ListMathFuncs(Tcl_Interp *interp, CONST char *pattern)
}
-
+declare 437 generic {
+ Tcl_Obj * Tcl_SubstObj(Tcl_Interp *interp, Tcl_Obj *objPtr, int flags)
+}
##############################################################################
diff --git a/generic/tcl.h b/generic/tcl.h
index 3e8a71a..a08cbc8 100644
--- a/generic/tcl.h
+++ b/generic/tcl.h
@@ -12,7 +12,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tcl.h,v 1.91 2001/06/08 20:06:11 dgp Exp $
+ * RCS: @(#) $Id: tcl.h,v 1.92 2001/07/12 13:15:09 dkf Exp $
*/
#ifndef _TCL
@@ -535,6 +535,15 @@ typedef struct stat *Tcl_Stat_;
#define TCL_RESULT_SIZE 200
/*
+ * Flags to control what substitutions are performed by Tcl_SubstObj():
+ */
+
+#define TCL_SUBST_COMMANDS 001
+#define TCL_SUBST_VARIABLES 002
+#define TCL_SUBST_BACKSLASHES 004
+#define TCL_SUBST_ALL 007
+
+/*
* Argument descriptors for math function callbacks in expressions:
*/
diff --git a/generic/tclCmdMZ.c b/generic/tclCmdMZ.c
index 5984ed0..1024430 100644
--- a/generic/tclCmdMZ.c
+++ b/generic/tclCmdMZ.c
@@ -13,7 +13,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclCmdMZ.c,v 1.39 2001/06/12 08:07:37 dkf Exp $
+ * RCS: @(#) $Id: tclCmdMZ.c,v 1.40 2001/07/12 13:15:09 dkf Exp $
*/
#include "tclInt.h"
@@ -2247,8 +2247,7 @@ Tcl_StringObjCmd(dummy, interp, objc, objv)
*
* This procedure is invoked to process the "subst" Tcl command.
* See the user documentation for details on what it does. This
- * command is an almost direct copy of an implementation by
- * Andrew Payne.
+ * command relies on Tcl_SubstObj() for its implementation.
*
* Results:
* A standard Tcl result.
@@ -2273,21 +2272,15 @@ Tcl_SubstObjCmd(dummy, interp, objc, objv)
enum substOptions {
SUBST_NOBACKSLASHES, SUBST_NOCOMMANDS, SUBST_NOVARS
};
- Interp *iPtr = (Interp *) interp;
- Tcl_DString result;
- char *p, *old, *value;
- int optionIndex, code, count, doVars, doCmds, doBackslashes, i;
+ Tcl_Obj *resultPtr;
+ int optionIndex, flags, i;
/*
* Parse command-line options.
*/
- doVars = doCmds = doBackslashes = 1;
+ flags = TCL_SUBST_ALL;
for (i = 1; i < (objc-1); i++) {
- p = Tcl_GetString(objv[i]);
- if (*p != '-') {
- break;
- }
if (Tcl_GetIndexFromObj(interp, objv[i], substOptions,
"switch", 0, &optionIndex) != TCL_OK) {
@@ -2295,15 +2288,15 @@ Tcl_SubstObjCmd(dummy, interp, objc, objv)
}
switch (optionIndex) {
case SUBST_NOBACKSLASHES: {
- doBackslashes = 0;
+ flags &= ~TCL_SUBST_BACKSLASHES;
break;
}
case SUBST_NOCOMMANDS: {
- doCmds = 0;
+ flags &= ~TCL_SUBST_COMMANDS;
break;
}
case SUBST_NOVARS: {
- doVars = 0;
+ flags &= ~TCL_SUBST_VARIABLES;
break;
}
default: {
@@ -2318,76 +2311,154 @@ Tcl_SubstObjCmd(dummy, interp, objc, objv)
}
/*
- * Scan through the string one character at a time, performing
- * command, variable, and backslash substitutions.
+ * Perform the substitution.
*/
+ resultPtr = Tcl_SubstObj(interp, objv[i], flags);
- Tcl_DStringInit(&result);
- old = p = Tcl_GetString(objv[i]);
- while (*p != 0) {
+ if (resultPtr == NULL) {
+ return TCL_ERROR;
+ }
+ Tcl_SetObjResult(interp, resultPtr);
+ return TCL_OK;
+}
+
+/*
+ *----------------------------------------------------------------------
+ *
+ * Tcl_SubstObjCmd --
+ *
+ * This function performs the substitutions specificed on the
+ * given string as described in the user documentation for the
+ * "subst" Tcl command. This code is heavily based on an
+ * implementation by Andrew Payne. Note that if a command
+ * substitution returns TCL_CONTINUE or TCL_RETURN from its
+ * evaluation and is not completely well-formed, the results are
+ * not defined.
+ *
+ * Results:
+ * A Tcl_Obj* containing the substituted string, or NULL to
+ * indicate that an error occurred.
+ *
+ * Side effects:
+ * See the user documentation.
+ *
+ *----------------------------------------------------------------------
+ */
+
+Tcl_Obj *
+Tcl_SubstObj(interp, objPtr, flags)
+ Tcl_Interp *interp;
+ Tcl_Obj *objPtr;
+ int flags;
+{
+ Tcl_Obj *resultObj;
+ char *p, *old;
+
+ old = p = Tcl_GetString(objPtr);
+ resultObj = Tcl_NewStringObj("", 0);
+ while (1) {
switch (*p) {
- case '\\':
- if (doBackslashes) {
- char buf[TCL_UTF_MAX];
+ case 0:
+ if (p != old) {
+ Tcl_AppendToObj(resultObj, old, p-old);
+ }
+ return resultObj;
- if (p != old) {
- Tcl_DStringAppend(&result, old, p-old);
- }
- Tcl_DStringAppend(&result, buf,
- Tcl_UtfBackslash(p, &count, buf));
- p += count;
- old = p;
- } else {
- p++;
+ case '\\':
+ if (flags & TCL_SUBST_BACKSLASHES) {
+ char buf[TCL_UTF_MAX];
+ int count;
+
+ if (p != old) {
+ Tcl_AppendToObj(resultObj, old, p-old);
}
- break;
+ Tcl_AppendToObj(resultObj, buf,
+ Tcl_UtfBackslash(p, &count, buf));
+ p += count;
+ old = p;
+ } else {
+ p++;
+ }
+ break;
- case '$':
- if (doVars) {
- if (p != old) {
- Tcl_DStringAppend(&result, old, p-old);
- }
- value = Tcl_ParseVar(interp, p, &p);
- if (value == NULL) {
- Tcl_DStringFree(&result);
- return TCL_ERROR;
- }
- Tcl_DStringAppend(&result, value, -1);
- old = p;
- } else {
+ case '$':
+ if (flags & TCL_SUBST_VARIABLES) {
+ Tcl_Parse parse;
+ Tcl_Obj *tempObj;
+
+ /*
+ * Code is simpler overall if we (effectively) inline
+ * Tcl_ParseVar, particularly as that allows us to use
+ * a non-string interface when we come to appending
+ * the variable contents to the result object. There
+ * are a few other optimisations that doing this
+ * enables (like being able to continue the run of
+ * unsubstituted characters straight through if a '$'
+ * does not precede a variable name.)
+ */
+ if (Tcl_ParseVarName(interp, p, -1, &parse, 0) != TCL_OK) {
+ goto errorResult;
+ }
+ if (parse.numTokens == 1) {
+ /*
+ * There isn't a variable name after all: the $ is
+ * just a $.
+ */
p++;
+ break;
}
- break;
+ if (p != old) {
+ Tcl_AppendToObj(resultObj, old, p-old);
+ }
+ p += parse.tokenPtr->size;
+ tempObj = Tcl_EvalTokens(interp, parse.tokenPtr,
+ parse.numTokens);
+ if (tempObj == NULL) {
+ goto errorResult;
+ }
+ Tcl_AppendObjToObj(resultObj, tempObj);
+ Tcl_DecrRefCount(tempObj);
+ old = p;
+ } else {
+ p++;
+ }
+ break;
- case '[':
- if (doCmds) {
- if (p != old) {
- Tcl_DStringAppend(&result, old, p-old);
- }
- iPtr->evalFlags = TCL_BRACKET_TERM;
- code = Tcl_Eval(interp, p+1);
- if (code == TCL_ERROR) {
- Tcl_DStringFree(&result);
- return code;
- }
- old = p = (p+1 + iPtr->termOffset+1);
- Tcl_DStringAppend(&result, iPtr->result, -1);
+ case '[':
+ if (flags & TCL_SUBST_COMMANDS) {
+ Interp *iPtr = (Interp *) interp;
+ int code;
+
+ if (p != old) {
+ Tcl_AppendToObj(resultObj, old, p-old);
+ }
+ iPtr->evalFlags = TCL_BRACKET_TERM;
+ code = Tcl_EvalEx(interp, p+1, -1, 0);
+ switch (code) {
+ case TCL_ERROR:
+ goto errorResult;
+ case TCL_BREAK:
Tcl_ResetResult(interp);
- } else {
- p++;
+ return resultObj;
+ default:
+ Tcl_AppendObjToObj(resultObj, Tcl_GetObjResult(interp));
+ case TCL_CONTINUE:
+ Tcl_ResetResult(interp);
+ old = p = (p+1 + iPtr->termOffset + 1);
}
- break;
-
- default:
+ } else {
p++;
- break;
+ }
+ break;
+ default:
+ p++;
+ break;
}
}
- if (p != old) {
- Tcl_DStringAppend(&result, old, p-old);
- }
- Tcl_DStringResult(interp, &result);
- return TCL_OK;
+
+ errorResult:
+ Tcl_DecrRefCount(resultObj);
+ return NULL;
}
/*
diff --git a/generic/tclDecls.h b/generic/tclDecls.h
index bb600ed..2e94d6a 100644
--- a/generic/tclDecls.h
+++ b/generic/tclDecls.h
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclDecls.h,v 1.51 2001/06/08 20:06:11 dgp Exp $
+ * RCS: @(#) $Id: tclDecls.h,v 1.52 2001/07/12 13:15:09 dkf Exp $
*/
#ifndef _TCLDECLS
@@ -1368,6 +1368,9 @@ EXTERN int Tcl_GetMathFuncInfo _ANSI_ARGS_((Tcl_Interp * interp,
/* 436 */
EXTERN Tcl_Obj * Tcl_ListMathFuncs _ANSI_ARGS_((Tcl_Interp * interp,
CONST char * pattern));
+/* 437 */
+EXTERN Tcl_Obj * Tcl_SubstObj _ANSI_ARGS_((Tcl_Interp * interp,
+ Tcl_Obj * objPtr, int flags));
typedef struct TclStubHooks {
struct TclPlatStubs *tclPlatStubs;
@@ -1864,6 +1867,7 @@ typedef struct TclStubs {
Tcl_UniChar * (*tcl_GetUnicodeFromObj) _ANSI_ARGS_((Tcl_Obj * objPtr, int * lengthPtr)); /* 434 */
int (*tcl_GetMathFuncInfo) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * name, int * numArgsPtr, Tcl_ValueType ** argTypesPtr, Tcl_MathProc ** procPtr, ClientData * clientDataPtr)); /* 435 */
Tcl_Obj * (*tcl_ListMathFuncs) _ANSI_ARGS_((Tcl_Interp * interp, CONST char * pattern)); /* 436 */
+ Tcl_Obj * (*tcl_SubstObj) _ANSI_ARGS_((Tcl_Interp * interp, Tcl_Obj * objPtr, int flags)); /* 437 */
} TclStubs;
#ifdef __cplusplus
@@ -3652,6 +3656,10 @@ extern TclStubs *tclStubsPtr;
#define Tcl_ListMathFuncs \
(tclStubsPtr->tcl_ListMathFuncs) /* 436 */
#endif
+#ifndef Tcl_SubstObj
+#define Tcl_SubstObj \
+ (tclStubsPtr->tcl_SubstObj) /* 437 */
+#endif
#endif /* defined(USE_TCL_STUBS) && !defined(USE_TCL_STUB_PROCS) */
diff --git a/generic/tclStubInit.c b/generic/tclStubInit.c
index cf8b8b9..1fe3582 100644
--- a/generic/tclStubInit.c
+++ b/generic/tclStubInit.c
@@ -8,7 +8,7 @@
* See the file "license.terms" for information on usage and redistribution
* of this file, and for a DISCLAIMER OF ALL WARRANTIES.
*
- * RCS: @(#) $Id: tclStubInit.c,v 1.52 2001/06/17 03:48:19 dgp Exp $
+ * RCS: @(#) $Id: tclStubInit.c,v 1.53 2001/07/12 13:15:09 dkf Exp $
*/
#include "tclInt.h"
@@ -832,6 +832,7 @@ TclStubs tclStubs = {
Tcl_GetUnicodeFromObj, /* 434 */
Tcl_GetMathFuncInfo, /* 435 */
Tcl_ListMathFuncs, /* 436 */
+ Tcl_SubstObj, /* 437 */
};
/* !END!: Do not edit above this line. */
diff --git a/tests/subst.test b/tests/subst.test
index 21b0d7e..662db99 100644
--- a/tests/subst.test
+++ b/tests/subst.test
@@ -11,7 +11,7 @@
# See the file "license.terms" for information on usage and redistribution
# of this file, and for a DISCLAIMER OF ALL WARRANTIES.
#
-# RCS: @(#) $Id: subst.test,v 1.8 2001/06/28 01:10:15 hobbs Exp $
+# RCS: @(#) $Id: subst.test,v 1.9 2001/07/12 13:15:09 dkf Exp $
if {[lsearch [namespace children] ::tcltest] == -1} {
package require tcltest
@@ -23,7 +23,7 @@ test subst-1.1 {basics} {
} {1 {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? string"}}
test subst-1.2 {basics} {
list [catch {subst a b c} msg] $msg
-} {1 {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? string"}}
+} {1 {bad switch "a": must be -nobackslashes, -nocommands, or -novariables}}
test subst-2.1 {simple strings} {
subst {}
@@ -90,7 +90,7 @@ test subst-6.1 {clear the result after command substitution} {
test subst-7.1 {switches} {
list [catch {subst foo bar} msg] $msg
-} {1 {wrong # args: should be "subst ?-nobackslashes? ?-nocommands? ?-novariables? string"}}
+} {1 {bad switch "foo": must be -nobackslashes, -nocommands, or -novariables}}
test subst-7.2 {switches} {
list [catch {subst -no bar} msg] $msg
} {1 {ambiguous switch "-no": must be -nobackslashes, -nocommands, or -novariables}}
@@ -148,19 +148,19 @@ test subst-9.2 {error in a subst} {
test subst-10.1 {break in a subst} {
subst {foo [break; bogus code] bar}
-} {foo bar}
+} {foo }
test subst-10.2 {break in a subst} {
subst {foo [break; return x; bogus code] bar}
-} {foo bar}
+} {foo }
test subst-10.3 {break in a subst} {
subst {foo [if 1 { break; bogus code}] bar}
-} {foo bar}
+} {foo }
test subst-10.4 {break in a subst, parse error} {
subst {foo [break ; set a {}{} ; stuff] bar}
-} {foo set a {}{} ; stuff] bar}
+} {foo }
test subst-10.5 {break in a subst, parse error} {
subst {foo [break ;set bar baz ;set a {}{} ; stuff] bar}
-} {foo set bar baz ;set a {}{} ; stuff] bar}
+} {foo }
test subst-11.1 {continue in a subst} {
subst {foo [continue; bogus code] bar}
diff --git a/unix/mkLinks b/unix/mkLinks
index fde23e4..1b57e15 100644
--- a/unix/mkLinks
+++ b/unix/mkLinks
@@ -234,7 +234,11 @@ if test -r CrtInterp.3; then
fi
if test -r CrtMathFnc.3; then
rm -f Tcl_CreateMathFunc.3
+ rm -f Tcl_GetMathFuncInfo.3
+ rm -f Tcl_ListMathFuncs.3
ln CrtMathFnc.3 Tcl_CreateMathFunc.3
+ ln CrtMathFnc.3 Tcl_GetMathFuncInfo.3
+ ln CrtMathFnc.3 Tcl_ListMathFuncs.3
fi
if test -r CrtObjCmd.3; then
rm -f Tcl_CreateObjCommand.3
@@ -928,6 +932,10 @@ if test -r StringObj.3; then
ln StringObj.3 Tcl_ConcatObj.3
ln StringObj.3 Tcl_AttemptSetObjLength.3
fi
+if test -r SubstObj.3; then
+ rm -f Tcl_SubstObj.3
+ ln SubstObj.3 Tcl_SubstObj.3
+fi
if test -r Tcl_Main.3; then
rm -f Tcl_SetMainLoop.3
ln Tcl_Main.3 Tcl_SetMainLoop.3