TIP 76: Make 'regsub' Return a String

Login
Bounty program for improvements to Tcl and certain Tcl packages.
Tcl 2017 Conference, Houston/TX, US, Oct 16-20
Send your abstracts to tclconference@googlegroups.com
by Aug 21.
State:		Final
Type:		Project
Tcl-Version:	8.4
Vote:		Done
Post-History:	
Author:		Bruce Hartweg <B.Hartweg@compaq.com>
Author:		Donal K. Fellows <dkf@users.sf.net>
Created:	29-Nov-2001

Abstract

This TIP proposes altering the [regsub] command so that it can return the substituted string as the result of the command.

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.

Specification

   regsub ?switches? exp string subSpec ?varName?

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

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: tcl/generic/tclCmdMZ.c

Function: Tcl_RegsubObjCmd

Currently (v 1.52):

    if (objc - idx != 4) {
	 Tcl_WrongNumArgs(interp, 1, objv,
		 "?switches? exp string subSpec varName");
	 return TCL_ERROR;
    }

which should be changed to:

    objc -= idx;
    if (objc != 3 || objc != 4) {
	 Tcl_WrongNumArgs(interp, 1, objv,
		 "?switches? exp string subSpec ?varName?");
	 return TCL_ERROR;
    }

and then at the end change this:

    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);
    }

to this:

    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);
    }

And then minor updates to the man page to show that varName is optional.

Copyright

This document has been placed in the public domain.

History