OSDN Git Service

From: Jan Wieck <jwieck@debis.com>
authorMarc G. Fournier <scrappy@hub.org>
Wed, 11 Feb 1998 14:14:18 +0000 (14:14 +0000)
committerMarc G. Fournier <scrappy@hub.org>
Wed, 11 Feb 1998 14:14:18 +0000 (14:14 +0000)
    A few minutes ago I sent down the PL/Tcl  directory  to  this
    list.  Look at it and reuse anything that might help to build
    PL/perl.  I really hope that PL/perl and PL/Tcl appear in the
    6.3 distribution. I'll do whatever I can to make this happen.

src/pl/tcl/modules/README [new file with mode: 0644]
src/pl/tcl/modules/pltcl_delmod [new file with mode: 0755]
src/pl/tcl/modules/pltcl_listmod [new file with mode: 0755]
src/pl/tcl/modules/pltcl_loadmod [new file with mode: 0755]
src/pl/tcl/modules/unknown.pltcl [new file with mode: 0644]

diff --git a/src/pl/tcl/modules/README b/src/pl/tcl/modules/README
new file mode 100644 (file)
index 0000000..4a948c5
--- /dev/null
@@ -0,0 +1,22 @@
+
+    The module support over the unknown command requires, that
+    the PL/Tcl call handler is compiled with -DPLTCL_UNKNOWN_SUPPORT.
+
+    Regular Tcl scripts of any size (over 8K :-) can be loaded into
+    the table pltcl_modules using the pltcl_loadmod script. The script
+    checks the modules that the procedure names don't overwrite
+    existing ones before doing anything. They also check for global
+    variables created at load time.
+
+    All procedures defined in the module files are automatically
+    added to the table pltcl_modfuncs. This table is used by the
+    unknown procedure to determine if an unknown command can be
+    loaded by sourcing a module. In that case the unknonw procedure
+    will silently source in the module and reexecute the original
+    command that invoked unknown.
+
+    I know, thist readme should be more explanatory - but time.
+
+
+Jan
+
diff --git a/src/pl/tcl/modules/pltcl_delmod b/src/pl/tcl/modules/pltcl_delmod
new file mode 100755 (executable)
index 0000000..79be7e5
--- /dev/null
@@ -0,0 +1,116 @@
+#!/bin/sh
+# Start tclsh \
+exec tclsh "$0" $@
+
+#
+# Code still has to be documented
+#
+
+#load /usr/local/pgsql/lib/libpgtcl.so
+package require Pgtcl
+
+
+#
+# Check for minimum arguments
+#
+if {$argc < 1} {
+    puts stderr ""
+    puts stderr "usage: pltcl_delmod dbname \[options\] modulename \[...\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+#
+# Remember database name and initialize options
+#
+set dbname [lindex $argv 0]
+set options ""
+set errors 0
+set opt ""
+set val ""
+
+set i 1
+while {$i < $argc} {
+    if {[string compare [string index [lindex $argv $i] 0] "-"] != 0} {
+        break;
+    }
+
+    set opt [lindex $argv $i]
+    incr i
+    if {$i >= $argc} {
+        puts stderr "no value given for option $opt"
+       incr errors
+       continue
+    }
+    set val [lindex $argv $i]
+    incr i
+
+    switch -- $opt {
+        -host {
+           append options "-host \"$val\" "
+       }
+       -port {
+           append options "-port $val "
+       }
+       default {
+           puts stderr "unknown option '$opt'"
+           incr errors
+       }
+    }
+}
+
+#
+# Final syntax check
+#
+if {$i >= $argc || $errors > 0} {
+    puts stderr ""
+    puts stderr "usage: pltcl_delmod dbname \[options\] modulename \[...\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+proc delmodule {conn modname} {
+    set xname $modname
+    regsub -all {\\} $xname {\\} xname
+    regsub -all {'}  $xname {''} xname
+
+    set found 0
+    pg_select $conn "select * from pltcl_modules where modname = '$xname'" \
+    MOD {
+        set found 1
+       break;
+    }
+
+    if {!$found} {
+        puts "Module $modname not found in pltcl_modules"
+       puts ""
+       return
+    }
+
+    pg_result \
+        [pg_exec $conn "delete from pltcl_modules where modname = '$xname'"] \
+       -clear
+    pg_result \
+        [pg_exec $conn "delete from pltcl_modfuncs where modname = '$xname'"] \
+       -clear
+
+    puts "Module $modname removed"
+}
+
+set conn [eval pg_connect $dbname $options]
+
+while {$i < $argc} {
+    delmodule $conn [lindex $argv $i]
+    incr i
+}
+
+pg_disconnect $conn
+
diff --git a/src/pl/tcl/modules/pltcl_listmod b/src/pl/tcl/modules/pltcl_listmod
new file mode 100755 (executable)
index 0000000..92de363
--- /dev/null
@@ -0,0 +1,122 @@
+#!/bin/sh
+# Start tclsh \
+exec tclsh "$0" $@
+
+#
+# Code still has to be documented
+#
+
+#load /usr/local/pgsql/lib/libpgtcl.so
+package require Pgtcl
+
+
+#
+# Check for minimum arguments
+#
+if {$argc < 1} {
+    puts stderr ""
+    puts stderr "usage: pltcl_listmod dbname \[options\] \[modulename \[...\]\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+#
+# Remember database name and initialize options
+#
+set dbname [lindex $argv 0]
+set options ""
+set errors 0
+set opt ""
+set val ""
+
+set i 1
+while {$i < $argc} {
+    if {[string compare [string index [lindex $argv $i] 0] "-"] != 0} {
+        break;
+    }
+
+    set opt [lindex $argv $i]
+    incr i
+    if {$i >= $argc} {
+        puts stderr "no value given for option $opt"
+       incr errors
+       continue
+    }
+    set val [lindex $argv $i]
+    incr i
+
+    switch -- $opt {
+        -host {
+           append options "-host \"$val\" "
+       }
+       -port {
+           append options "-port $val "
+       }
+       default {
+           puts stderr "unknown option '$opt'"
+           incr errors
+       }
+    }
+}
+
+#
+# Final syntax check
+#
+if {$errors > 0} {
+    puts stderr ""
+    puts stderr "usage: pltcl_listmod dbname \[options\] \[modulename \[...\]\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+proc listmodule {conn modname} {
+    set xname $modname
+    regsub -all {\\} $xname {\\} xname
+    regsub -all {'}  $xname {''} xname
+
+    set found 0
+    pg_select $conn "select * from pltcl_modules where modname = '$xname'" \
+    MOD {
+        set found 1
+       break;
+    }
+
+    if {!$found} {
+        puts "Module $modname not found in pltcl_modules"
+       puts ""
+       return
+    }
+
+    puts "Module $modname defines procedures:"
+    pg_select $conn "select funcname from pltcl_modfuncs \
+           where modname = '$xname' order by funcname" FUNC {
+        puts "    $FUNC(funcname)"
+    }
+    puts ""
+}
+
+set conn [eval pg_connect $dbname $options]
+
+if {$i == $argc} {
+    pg_select $conn "select distinct modname from pltcl_modules        \
+               order by modname"       \
+               MOD {
+        listmodule $conn $MOD(modname)
+    }
+} else {
+    while {$i < $argc} {
+        listmodule $conn [lindex $argv $i]
+       incr i
+    }
+}
+
+pg_disconnect $conn
+
diff --git a/src/pl/tcl/modules/pltcl_loadmod b/src/pl/tcl/modules/pltcl_loadmod
new file mode 100755 (executable)
index 0000000..d437f76
--- /dev/null
@@ -0,0 +1,502 @@
+#!/bin/sh
+# Start tclsh \
+exec tclsh "$0" $@
+
+#
+# Code still has to be documented
+#
+
+#load /usr/local/pgsql/lib/libpgtcl.so
+package require Pgtcl
+
+
+#
+# Check for minimum arguments
+#
+if {$argc < 2} {
+    puts stderr ""
+    puts stderr "usage: pltcl_loadmod dbname \[options\] file \[...\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+#
+# Remember database name and initialize options
+#
+set dbname [lindex $argv 0]
+set options ""
+set errors 0
+set opt ""
+set val ""
+
+set i 1
+while {$i < $argc} {
+    if {[string compare [string index [lindex $argv $i] 0] "-"] != 0} {
+        break;
+    }
+
+    set opt [lindex $argv $i]
+    incr i
+    if {$i >= $argc} {
+        puts stderr "no value given for option $opt"
+       incr errors
+       continue
+    }
+    set val [lindex $argv $i]
+    incr i
+
+    switch -- $opt {
+        -host {
+           append options "-host \"$val\" "
+       }
+       -port {
+           append options "-port $val "
+       }
+       default {
+           puts stderr "unknown option '$opt'"
+           incr errors
+       }
+    }
+}
+
+#
+# Final syntax check
+#
+if {$i >= $argc || $errors > 0} {
+    puts stderr ""
+    puts stderr "usage: pltcl_loadmod dbname \[options\] file \[...\]"
+    puts stderr ""
+    puts stderr "options:"
+    puts stderr "    -host hostname"
+    puts stderr "    -port portnumber"
+    puts stderr ""
+    exit 1
+}
+
+
+proc __PLTcl_loadmod_check_table {conn tabname expnames exptypes} {
+    set attrs [expr [llength $expnames] - 1]
+    set error 0
+    set found 0
+
+    pg_select $conn "select C.relname, A.attname, A.attnum, T.typname  \
+               from pg_class C, pg_attribute A, pg_type T              \
+               where C.relname = '$tabname'                            \
+                 and A.attrelid = C.oid                                \
+                 and A.attnum > 0                                      \
+                 and T.oid = A.atttypid                                \
+               order by attnum" tup {
+
+       incr found
+       set i $tup(attnum)
+
+       if {$i > $attrs} {
+           puts stderr "Table $tabname has extra field '$tup(attname)'"
+           incr error
+           continue
+       }
+
+       set xname [lindex $expnames $i]
+       set xtype [lindex $exptypes $i]
+
+       if {[string compare $tup(attname) $xname] != 0} {
+           puts stderr "Attribute $i of $tabname has wrong name"
+           puts stderr "    got '$tup(attname)' expected '$xname'"
+           incr error
+       }
+       if {[string compare $tup(typname) $xtype] != 0} {
+           puts stderr "Attribute $i of $tabname has wrong type"
+           puts stderr "    got '$tup(typname)' expected '$xtype'"
+           incr error
+       }
+    }
+
+    if {$found == 0} {
+        return 0
+    }
+
+    if {$found < $attrs} {
+       incr found
+       set miss [lrange $expnames $found end]
+        puts "Table $tabname doesn't have field(s) $miss"
+       incr error
+    }
+
+    if {$error > 0} {
+        return 2
+    }
+
+    return 1
+}
+
+
+proc __PLTcl_loadmod_check_tables {conn} {
+    upvar #0   __PLTcl_loadmod_status  status
+
+    set error 0
+
+    set names {{} modname modseq modsrc}
+    set types {{} name int2 text}
+
+    switch [__PLTcl_loadmod_check_table $conn pltcl_modules $names $types] {
+        0 {
+           set status(create_table_modules) 1
+       }
+       1 {
+           set status(create_table_modules) 0
+       }
+       2 {
+           puts "Error(s) in table pltcl_modules"
+           incr error
+       }
+    }
+
+    set names {{} funcname modname}
+    set types {{} name name}
+
+    switch [__PLTcl_loadmod_check_table $conn pltcl_modfuncs $names $types] {
+        0 {
+           set status(create_table_modfuncs) 1
+       }
+       1 {
+           set status(create_table_modfuncs) 0
+       }
+       2 {
+           puts "Error(s) in table pltcl_modfuncs"
+           incr error
+       }
+    }
+
+    if {$status(create_table_modfuncs) && !$status(create_table_modules)} {
+        puts stderr "Table pltcl_modfuncs doesn't exist but pltcl_modules does"
+       puts stderr "Either both tables must be present or none."
+       incr error
+    }
+
+    if {$status(create_table_modules) && !$status(create_table_modfuncs)} {
+        puts stderr "Table pltcl_modules doesn't exist but pltcl_modfuncs does"
+       puts stderr "Either both tables must be present or none."
+       incr error
+    }
+
+    if {$error} {
+        puts stderr ""
+       puts stderr "Abort"
+       exit 1
+    }
+
+    if {!$status(create_table_modules)} {
+        __PLTcl_loadmod_read_current $conn
+    }
+}
+
+
+proc __PLTcl_loadmod_read_current {conn} {
+    upvar #0   __PLTcl_loadmod_status          status
+    upvar #0   __PLTcl_loadmod_modsrc          modsrc
+    upvar #0   __PLTcl_loadmod_funclist        funcs
+    upvar #0   __PLTcl_loadmod_globlist        globs
+
+    set errors 0
+
+    set curmodlist ""
+    pg_select $conn "select distinct modname from pltcl_modules" mtup {
+       set mname $mtup(modname);
+        lappend curmodlist $mname
+    }
+
+    foreach mname $curmodlist {
+       set srctext ""
+        pg_select $conn "select * from pltcl_modules           \
+               where modname = '$mname'                        \
+               order by modseq" tup {
+           append srctext $tup(modsrc)
+        }
+
+       if {[catch {
+               __PLTcl_loadmod_analyze                         \
+                       "Current $mname"                        \
+                       $mname                                  \
+                       $srctext new_globals new_functions
+           }]} {
+           incr errors
+        }
+       set modsrc($mname) $srctext
+       set funcs($mname) $new_functions
+       set globs($mname) $new_globals
+    }
+
+    if {$errors} {
+        puts stderr ""
+        puts stderr "Abort"
+       exit 1
+    }
+}
+
+
+proc __PLTcl_loadmod_analyze {modinfo modname srctext v_globals v_functions} {
+    upvar 1    $v_globals new_g
+    upvar 1    $v_functions new_f
+    upvar #0   __PLTcl_loadmod_allfuncs        allfuncs
+    upvar #0   __PLTcl_loadmod_allglobs        allglobs
+
+    set errors 0
+
+    set old_g [info globals]
+    set old_f [info procs]
+    set new_g ""
+    set new_f ""
+
+    if {[catch {
+           uplevel #0 "$srctext"
+        } msg]} {
+        puts "$modinfo: $msg"
+       incr errors
+    }
+
+    set cur_g [info globals]
+    set cur_f [info procs]
+
+    foreach glob $cur_g {
+        if {[lsearch -exact $old_g $glob] >= 0} {
+           continue
+       }
+       if {[info exists allglobs($glob)]} {
+           puts stderr "$modinfo: Global $glob previously used in module $allglobs($glob)"
+           incr errors
+       } else {
+           set allglobs($glob) $modname
+       }
+       lappend new_g $glob
+       uplevel #0 unset $glob
+    }
+    foreach func $cur_f {
+        if {[lsearch -exact $old_f $func] >= 0} {
+           continue
+       }
+       if {[info exists allfuncs($func)]} {
+           puts stderr "$modinfo: Function $func previously defined in module $allfuncs($func)"
+           incr errors
+       } else {
+           set allfuncs($func) $modname
+       }
+       lappend new_f $func
+       rename $func {}
+    }
+
+    if {$errors} {
+        return -code error
+    }
+    #puts "globs in $modname: $new_g"
+    #puts "funcs in $modname: $new_f"
+}
+
+
+proc __PLTcl_loadmod_create_tables {conn} {
+    upvar #0   __PLTcl_loadmod_status  status
+
+    if {$status(create_table_modules)} {
+        if {[catch {
+               set res [pg_exec $conn                          \
+                   "create table pltcl_modules (               \
+                       modname name,                           \
+                       modseq  int2,                           \
+                       modsrc  text);"]
+           } msg]} {
+           puts stderr "Error creating table pltcl_modules"
+           puts stderr "    $msg"
+           exit 1
+       }
+        if {[catch {
+               set res [pg_exec $conn                          \
+                   "create index pltcl_modules_i               \
+                       on pltcl_modules using btree            \
+                       (modname name_ops);"]
+           } msg]} {
+           puts stderr "Error creating index pltcl_modules_i"
+           puts stderr "    $msg"
+           exit 1
+       }
+       puts "Table pltcl_modules created"
+       pg_result $res -clear
+    }
+
+    if {$status(create_table_modfuncs)} {
+        if {[catch {
+               set res [pg_exec $conn                          \
+                   "create table pltcl_modfuncs (              \
+                       funcname name,                          \
+                       modname  name);"]
+           } msg]} {
+           puts stderr "Error creating table pltcl_modfuncs"
+           puts stderr "    $msg"
+           exit 1
+       }
+        if {[catch {
+               set res [pg_exec $conn                          \
+                   "create index pltcl_modfuncs_i              \
+                       on pltcl_modfuncs using hash            \
+                       (funcname name_ops);"]
+           } msg]} {
+           puts stderr "Error creating index pltcl_modfuncs_i"
+           puts stderr "    $msg"
+           exit 1
+       }
+       puts "Table pltcl_modfuncs created"
+       pg_result $res -clear
+    }
+}
+
+
+proc __PLTcl_loadmod_read_new {conn} {
+    upvar #0   __PLTcl_loadmod_status          status
+    upvar #0   __PLTcl_loadmod_modsrc          modsrc
+    upvar #0   __PLTcl_loadmod_funclist        funcs
+    upvar #0   __PLTcl_loadmod_globlist        globs
+    upvar #0   __PLTcl_loadmod_allfuncs        allfuncs
+    upvar #0   __PLTcl_loadmod_allglobs        allglobs
+    upvar #0   __PLTcl_loadmod_modlist         modlist
+
+    set errors 0
+
+    set new_modlist ""
+    foreach modfile $modlist {
+        set modname [file rootname [file tail $modfile]]
+       if {[catch {
+               set fid [open $modfile "r"]
+           } msg]} {
+           puts stderr $msg
+           incr errors
+           continue
+        }
+       set srctext [read $fid]
+       close $fid
+
+       if {[info exists modsrc($modname)]} {
+           if {[string compare $modsrc($modname) $srctext] == 0} {
+               puts "Module $modname unchanged - ignored"
+               continue
+           }
+           foreach func $funcs($modname) {
+               unset allfuncs($func)
+           }
+           foreach glob $globs($modname) {
+               unset allglobs($glob)
+           }
+           unset funcs($modname)
+           unset globs($modname)
+           set modsrc($modname) $srctext
+           lappend new_modlist $modname
+       } else {
+           set modsrc($modname) $srctext
+           lappend new_modlist $modname
+       }
+
+       if {[catch {
+               __PLTcl_loadmod_analyze "New/updated $modname"  \
+                       $modname $srctext new_globals new_funcs
+           }]} {
+           incr errors
+       }
+
+       set funcs($modname) $new_funcs
+       set globs($modname) $new_globals
+    }
+
+    if {$errors} {
+        puts stderr ""
+        puts stderr "Abort"
+       exit 1
+    }
+
+    set modlist $new_modlist
+}
+
+
+proc __PLTcl_loadmod_load_modules {conn} {
+    upvar #0   __PLTcl_loadmod_modsrc          modsrc
+    upvar #0   __PLTcl_loadmod_funclist        funcs
+    upvar #0   __PLTcl_loadmod_modlist         modlist
+
+    set errors 0
+
+    foreach modname $modlist {
+       set xname [__PLTcl_loadmod_quote $modname]
+
+        pg_result [pg_exec $conn "begin;"] -clear
+
+       pg_result [pg_exec $conn                                \
+               "delete from pltcl_modules where modname = '$xname'"] -clear
+       pg_result [pg_exec $conn                                \
+               "delete from pltcl_modfuncs where modname = '$xname'"] -clear
+
+       foreach func $funcs($modname) {
+           set xfunc [__PLTcl_loadmod_quote $func]
+           pg_result [                                                 \
+               pg_exec $conn "insert into pltcl_modfuncs values (      \
+                       '$xfunc', '$xname')"                            \
+           ] -clear
+       }
+       set i 0
+       set srctext $modsrc($modname)
+       while {[string compare $srctext ""] != 0} {
+           set xpart [string range $srctext 0 3999]
+           set xpart [__PLTcl_loadmod_quote $xpart]
+           set srctext [string range $srctext 4000 end]
+
+           pg_result [                                                 \
+               pg_exec $conn "insert into pltcl_modules values (       \
+                       '$xname', $i, '$xpart')"                        \
+           ] -clear
+       }
+
+        pg_result [pg_exec $conn "commit;"] -clear
+
+       puts "Successfully loaded/updated module $modname"
+    }
+}
+
+
+proc __PLTcl_loadmod_quote {s} {
+    regsub -all {\\} $s {\\\\} s
+    regsub -all {'}  $s {''} s
+    return $s
+}
+
+
+set __PLTcl_loadmod_modlist [lrange $argv $i end]
+set __PLTcl_loadmod_modsrc(dummy) ""
+set __PLTcl_loadmod_funclist(dummy) ""
+set __PLTcl_loadmod_globlist(dummy) ""
+set __PLTcl_loadmod_allfuncs(dummy) ""
+set __PLTcl_loadmod_allglobs(dummy) ""
+
+unset __PLTcl_loadmod_modsrc(dummy)
+unset __PLTcl_loadmod_funclist(dummy)
+unset __PLTcl_loadmod_globlist(dummy)
+unset __PLTcl_loadmod_allfuncs(dummy)
+unset __PLTcl_loadmod_allglobs(dummy)
+
+
+puts ""
+
+set __PLTcl_loadmod_conn [eval pg_connect $dbname $options]
+
+unset i dbname options errors opt val
+
+__PLTcl_loadmod_check_tables $__PLTcl_loadmod_conn
+
+__PLTcl_loadmod_read_new $__PLTcl_loadmod_conn
+
+__PLTcl_loadmod_create_tables $__PLTcl_loadmod_conn
+__PLTcl_loadmod_load_modules $__PLTcl_loadmod_conn
+
+pg_disconnect $__PLTcl_loadmod_conn
+
+puts ""
+
+
diff --git a/src/pl/tcl/modules/unknown.pltcl b/src/pl/tcl/modules/unknown.pltcl
new file mode 100644 (file)
index 0000000..830ee25
--- /dev/null
@@ -0,0 +1,65 @@
+#---------------------------------------------------------------------
+# Support for unknown command
+#---------------------------------------------------------------------
+
+proc unknown {proname args} {
+    upvar #0   __PLTcl_unknown_support_plan_modname    p_mod
+    upvar #0   __PLTcl_unknown_support_plan_modsrc     p_src
+
+    #-----------------------------------------------------------
+    # On first call prepare the plans
+    #-----------------------------------------------------------
+    if {![info exists p_mod]} {
+        set p_mod [SPI_prepare                                         \
+               "select modname from pltcl_modfuncs             \
+                where funcname = \$1" name]
+        set p_src [SPI_prepare                                 \
+               "select modseq, modsrc from pltcl_modules       \
+                where modname = \$1                            \
+                order by modseq" name]
+    }
+
+    #-----------------------------------------------------------
+    # Lookup the requested function in pltcl_modfuncs
+    #-----------------------------------------------------------
+    set n [SPI_execp -count 1 $p_mod [list [quote $proname]]]
+    if {$n != 1} {
+       #-----------------------------------------------------------
+       # Not found there either - now it's really unknown
+       #-----------------------------------------------------------
+        return -code error "unknown command '$proname'"
+    }
+
+    #-----------------------------------------------------------
+    # Collect the source pieces from pltcl_modules
+    #-----------------------------------------------------------
+    set src ""
+    SPI_execp $p_src [list [quote $modname]] {
+        append src $modsrc
+    }
+
+    #-----------------------------------------------------------
+    # Load the source into the interpreter
+    #-----------------------------------------------------------
+    if {[catch {
+            uplevel #0 "$src"
+        } msg]} {
+       elog NOTICE "pltcl unknown: error while loading module $modname"
+       elog WARN $msg
+    }
+
+    #-----------------------------------------------------------
+    # This should never happen
+    #-----------------------------------------------------------
+    if {[catch {info args $proname}]} {
+        return -code error \
+           "unknown command '$proname' (still after loading module $modname)"
+    }
+
+    #-----------------------------------------------------------
+    # Finally simulate the initial procedure call
+    #-----------------------------------------------------------
+    return [uplevel 1 $proname $args]
+}
+
+