\documentclass[]{article}
\usepackage{amsmath,graphicx,supertabular,hyperref,tabularx,ifthen}
\title{TIP \#76: Make 'regsub' Return a String}
\date{November 29, 2001}
\author{Bruce Hartweg, Donal K. Fellows}
\urlstyle{sf}
\setlength{\parskip}{1ex}
\setlength{\parindent}{0pt}
\def\tipversion$#1${\texttt{\$#1\$}}
\def\tiplangle#1{\ensuremath{<}}
\def\tiprangle#1{\ensuremath{>}}
\def\tipbar#1{\ensuremath{|}}
\def\tipmail#1#2{\(\langle\){\small\expandafter\url{#1@#2}}\(\rangle\)}
\ifx\pdfoutput\undefined
\newcommand{\tipimage}[2]{\typeout{Make sure you download #1.eps}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.eps}}{\includegraphics[width=0.8\textwidth]{#1.eps}}}
\newcommand{\tipxref}[1]{}
\newcommand{\tipxrefend}{}
\else
\newcommand{\tipimage}[2]{\typeout{Make sure you create #1.pdf}\ifthenelse{\lengthtest{0.8\textwidth>#2}\and\lengthtest{0pt<#2}}{\includegraphics{#1.pdf}}{\includegraphics[width=0.8\textwidth]{#1.pdf}}}
\pdfcatalog{/PageMode /UseOutlines}
\newcommand{\tipxref}[1]{\pdfannotlink attr {/C [0.5 0.5 1.0] /Border [0 0 1]} goto name {#1}}
\newcommand{\tipxrefend}{\pdfendlink}
\fi
\newenvironment{tipabstract}{\begin{abstract}}{\end{abstract}}
\begin{document}\maketitle
\begin{center}\begin{tabularx}{\linewidth}{|r@{: }X|}\hline
\textbf{TIP \#76}&\textbf{Make 'regsub' Return a String}\\\hline
Author&

Bruce Hartweg \tipmail{B.Hartweg}{compaq.com}
\par
Donal K. Fellows \tipmail{dkf}{users.sf.net}
\\
Created&Thursday, \(\text{29}^{\text{th}}\) November 2001\\
Type&Project\\
Tcl Version&\(8.4\)\\
State&Final\\
Vote&Done\\
Version&\tipversion$Revision: 1.3 $\\
Post History&\\
\hline\end{tabularx}\end{center}
\thispagestyle{empty}\pagestyle{empty}
\begin{tipabstract}

This TIP proposes altering the [regsub] command so that it can return the substituted string as the result of the command.
\end{tipabstract}
\tableofcontents\setcounter{page}{0}\clearpage\pagestyle{plain}

\section{Rationale}

In many of the most common uses of the [regsub] command, the substituted string is used only once in the immediately following command. However, the [regsub] command only provides the substituted string via a variable, with the result of the command itself being the number of substitutions performed. For many uses of the command, it is the substituted string though that is the most useful result, especially if some other transformation is going to be applied to it (like further [regsub] commands or some other Tcl command like one of the [string] subcommands or [subst].) This TIP proposes a mechanism for providing the ability to return the string as the command's result, and in a way that is backward-compatible with existing scripts.

\section{Specification}
\begingroup\small\begin{verbatim}
   regsub ?switches? exp string subSpec ?varName?
\end{verbatim}
\endgroup

If \textit{varName} is supplied the new string is written there and the number of substitutions are returned (same as current behavior). If \textit{varName} is not supplied than the new string is returned as the result of the [regsub] command.

\section{Reference Implementation}

This is a pretty easy change, although I do not currently have an environment where I can actually build and test this the following should create the desired behavior.

File: \textit{tcl/generic/tclCmdMZ.c}

Function: \textit{Tcl\_RegsubObjCmd}

Currently (v 1.52):
\begingroup\small\begin{verbatim}
    if (objc - idx != 4) {
	 Tcl_WrongNumArgs(interp, 1, objv,
		 "?switches? exp string subSpec varName");
	 return TCL_ERROR;
    }
\end{verbatim}
\endgroup

which should be changed to:
\begingroup\small\begin{verbatim}
    objc -= idx;
    if (objc != 3 || objc != 4) {
	 Tcl_WrongNumArgs(interp, 1, objv,
		 "?switches? exp string subSpec ?varName?");
	 return TCL_ERROR;
    }
\end{verbatim}
\endgroup

and then at the end change this:
\begingroup\small\begin{verbatim}
    if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, 0) == NULL) {
	 Tcl_AppendResult(interp, "couldn't set variable \"",
		 Tcl_GetString(objv[3]), "\"", (char *) NULL);
	 result = TCL_ERROR;
    } else {
	 /*
	  * Set the interpreter's object result to an integer object
	  * holding the number of matches.
	  */

	 Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches);
    }
\end{verbatim}
\endgroup

to this:
\begingroup\small\begin{verbatim}
    if (objc == 4) {
        if (Tcl_ObjSetVar2(interp, objv[3], NULL, resultPtr, 0) == NULL) {
            Tcl_AppendResult(interp, "couldn't set variable \"",
        	     Tcl_GetString(objv[3]), "\"", (char *) NULL);
            result = TCL_ERROR;
        } else {
            /*
             * Set the interpreter's object result to an integer object
             * holding the number of matches.
             */

            Tcl_SetIntObj(Tcl_GetObjResult(interp), numMatches);
        }
    } else {
           /*
            * No varname supplied, return string as result
            */
           Tcl_SetObjResult(interp, resultPtr);
    }
\end{verbatim}
\endgroup

And then minor updates to the man page to show that \textit{varName} is optional.

\section{Copyright}

This document has been placed in the public domain.

\section{Colophon}

\textit{TIP AutoGenerator --- written by Donal K. Fellows}
\end{document}
