1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218
|
# -*- Tcl -*-
#
# Define a basic set of predefined Tcl commands and definitions for
# the Next Scripting Framework. This file will be transformed by
# mk_predefined.tcl into "predefined.h", which in included in nsf.c.
#
# Copyright (C) 2009-2021 Gustaf Neumann
# Copyright (C) 2010 Stefan Sobernig
#
# The predefined code has to be split into 2 parts due to a string
# literal limitation in ISO C99, that requires compilers to support
# only strings up to 4095 bytes.
#
# This is part 1.
#
namespace eval ::nsf {
#
# get frequenly used primitiva into the ::nsf namespace
#
# Symbols reused in the next scripting language
namespace export \
next current self configure finalize interp is my relation dispatch
namespace eval ::nsf::method::create {namespace export alias}
#
# support for method provide and method require
#
proc ::nsf::method::provide {require_name definition {script ""}} {
set ::nsf::methodIndex($require_name) [list definition $definition script $script]
}
proc ::nsf::method::require {object name {per_object 0}} {
#
# On a method require, the optional script is evaluated and the
# "definition" gets inserted
# - on posiiton 1 the actual object
# - on posiiton 2 optionally "-per-object"
#
# The definition cmd must return the method handle.
#
set key ::nsf::methodIndex($name)
if {[info exists $key]} {
array set "" [set $key]
if {$(script) ne ""} {
eval $(script)
}
if {$per_object} {
set cmd [linsert $(definition) 1 -per-object]
return [eval [linsert $cmd 1 $object]]
} else {
return [eval [linsert $(definition) 1 $object]]
}
} else {
error "cannot require method $name for $object, method unknown"
}
}
#
# The following helper proc is used e.g. in OpenACS to pair
# introspection with nsf::procs.
#
::proc strip_proc_name {name} {
if {[string match ::nsf::procs::* $name]} {
return [string range $name 12 end]
} elseif {[string match nsf::procs::* $name]} {
return [string range $name 12 end]
} else {
return $name
}
}
#
# ::nsf::mixin
#
# Provide a similar interface as for ::nsf::method::create, ::nsf::method::alias,
# etc.. Semantically, ::nsf::mixin behaves like a "mixin add", but
# can be used as well for deleting the mixin list (empty last
# argument).
#
::nsf::proc ::nsf::mixin {object -per-object:switch classes} {
set rel [expr {${per-object} ? "object-mixin" : "class-mixin"}]
if {[lindex $classes 0] ne ""} {
set oldSetting [::nsf::relation::get $object $rel]
# use uplevel to avoid namespace surprises
uplevel [list ::nsf::relation::set $object $rel [linsert $oldSetting 0 $classes]]
} else {
uplevel [list ::nsf::relation::set $object $rel ""]
}
}
#
# provide some popular methods for "method require"
#
::nsf::method::provide autoname {::nsf::method::alias autoname ::nsf::methods::object::autoname}
::nsf::method::provide exists {::nsf::method::alias exists ::nsf::methods::object::exists}
::nsf::method::provide volatile {::nsf::method::alias volatile ::nsf::methods::object::volatile}
######################################################################
# unknown handler for objects and classes
#
proc ::nsf::object::unknown {name} {
foreach {key handler} [array get ::nsf::object::unknown] {
set result [uplevel [list {*}$handler $name]]
if {$result ne ""} {
return $result
}
}
return ""
}
namespace eval ::nsf::object::unknown {
proc add {key handler} {set ::nsf::object::unknown($key) $handler}
proc get {key} {return $::nsf::object::unknown($key)}
proc delete {key} {array unset ::nsf::object::unknown($key)}
proc keys {} {array names ::nsf::object::unknown}
}
# Example unknown handler:
# ::nsf::object::unknown::add xotcl {::xotcl::Class __unknown}
namespace eval ::nsf::argument {}
proc ::nsf::argument::unknown {args} {
#puts stderr "??? ::nsf::argument::unknown <$args> [info frame -1]"
return ""
}
######################################################################
# exit handlers
#
proc ::nsf::exithandler {args} {
lassign $args op value
switch $op {
set {::proc ::nsf::__exithandler {} $value}
get {::info body ::nsf::__exithandler}
unset {proc ::nsf::__exithandler args {;}}
default {error "syntax: ::nsf::exithandler $::nsf::parameter::syntax(::nsf::exithandler)"}
}
}
# initialize exit handler
::nsf::exithandler unset
#
# logger
#
if {[info command ::ns_log] ne ""} {
proc ::nsf::log {level msg} {
# The function might be called in situations in
# aolserver/NaviServer, where ns_log is not available.
if {[info command ::ns_log] ne ""} {
::ns_log $level "nsf: $msg"
} else {
puts stderr "$level: $msg"
}
}
} else {
proc ::nsf::log {level msg} {
puts stderr "$level: $msg"
}
}
#
# debug::call and debug::exit command
#
namespace eval ::nsf::debug {}
proc ::nsf::debug::call {level objectInfo methodInfo arglist} {
nsf::log Debug "call($level) - $objectInfo $methodInfo $arglist"
}
proc ::nsf::debug::exit {level objectInfo methodInfo result usec} {
nsf::log Debug "exit($level) - $objectInfo $methodInfo $usec usec -> $result"
}
#
# deprecated command
#
proc ::nsf::deprecated {what oldCmd newCmd} {
set msg "*** $what $oldCmd is deprecated."
if {$newCmd ne ""} {append msg " use $newCmd instead."}
#append msg "\n**\n"
nsf::log Warning $msg
}
#
# determine platform aware temp directory
#
proc tmpdir {} {
foreach e [list TMPDIR TEMP TMP] {
if {[info exists ::env($e)] \
&& [file isdirectory $::env($e)] \
&& [file writable $::env($e)]} {
return $::env($e)
}
}
if {$::tcl_platform(platform) eq "windows"} {
foreach d [list "C:\\TEMP" "C:\\TMP" "\\TEMP" "\\TMP"] {
if {[file isdirectory $d] && [file writable $d]} {
return $d
}
}
}
return /tmp
}
namespace export tmpdir
# if HOME is not set, and ~ is resolved, Tcl chokes on that
if {![info exists ::env(HOME)]} {set ::env(HOME) /root}
}
#
# Local variables:
# mode: tcl
# tcl-indent-level: 2
# indent-tabs-mode: nil
# End:
|