if {[catch {trace info variable ""}]} {
    # We don't have the new-style trace commands.  Just do a few, for snit.

    rename trace Trace
    proc trace {args} {
        # Adapt the builtin trace command to have add and remove subcommands.

        if {[llength $args] == 0} {
            error "wrong # args: should be \"trace option ?arg arg ...?\""
        }

        # Determine what the subcommand will be, assuming type "variable".
        # Also chain to builtin trace for old-style and invalid subcommands.
        switch -exact [set subcommand [lindex $args 0]] {
        add     {set cmd variable}
        remove  {set cmd vdelete}
        info    {set cmd vinfo}
        default {return [uplevel Trace [lrange $args 0 end]]}
        }

        if {[llength $args] == 1} {
            error "wrong # args: should be \"trace $subcommand\
                    type ?arg arg ...?\""
        }

        # This emulation can only handle type "variable".
        switch -exact [set type [lindex $args 1]] {
        variable {
        } command - execution {
            # Comment this to silently ignore unimplemented subcommands.
            #error "not implemented: trace $subcommand $type"
            return
        } default {
            error "bad option \"$type\": must be execution,\
                    command, or variable"
        }}
        
        # If doing an add or remove, determine what the operation set will be.
        # If doing an info, well, things are easier.
        if {[string compare $subcommand info] != 0} {
            # add or remove.

            if {[llength $args] != 5} {
                error "wrong # args: should be \"trace $subcommand\
                        $type name opList command\""
            }

            # Build the ops list.
            set ops ""
            foreach op [set opList [lindex $args 3]] {
                switch -exact $op {
                array   {append ops a}
                read    {append ops r}
                write   {append ops w}
                unset   {append ops u}
                default {
                    error "bad operation \"$op\": must be array,\
                            read, unset, or write"
                }}
            }

            # Extract miscellaneous fields.
            set name [lindex $args 2]
            set command [lindex $args 4]

            # Chain to the old-style variable or vdelete subcommand.
            return [uplevel Trace $cmd [list $name] $ops [list $command]]
        } else {
            # info.

            if {[llength $args] != 3} {
                error "wrong # args: should be \"trace $subcommand $type name\""
            }

            # Extract miscellaneous fields.
            set name [lindex $args 2]

            # Chain to the old-style vinfo subcommand.
            return [uplevel Trace $cmd [list $name]]
        }
    }
}

if {[catch {namespace exists ::}]} {
    # We don't have namespace exists, but it can be easily emulated.

    rename namespace Namespace
    proc namespace {args} {
        # Adapt the builtin namespace command to have an exists subcommand.

        if {[llength $args] == 0} {
            error "wrong # args: should be \"namespace subcommand ?arg ...?\""
        }

        set subcommand [lindex $args 0]
        switch -exact $subcommand {
        exists {
            # Emulate namespace exists by calling namespace children instead.
            # If namespace throws an error, then the namespace doesn't exist.

            if {[llength $args] != 2} {
                error "wrong # args: should be \"namespace exists name\""
            }
            return [expr {![catch {
                    uplevel Namespace children [lrange $args 1 end]
                    }]}]
        } default {
            # For all else, chain to the normal namespace command.

            return [uplevel Namespace [lrange $args 0 end]]
        }}
    }
}
# vi:sw=4 sts=4 ts=8 et

