nsupported url type \"$proto\"" } set old $urlTypes($proto) unset urlTypes($proto) return $old } # http::config -- # # See documentation for details. # # Arguments: # args Options parsed by the procedure. # Results: # TODO proc http::config {args} { variable http set options [lsort [array names http -*]] set usage [join $options ", "] if {[llength $args] == 0} { set result {} foreach name $options { lappend result $name $http($name) } return $result } set options [string map {- ""} $options] set pat ^-([join $options |])$ if {[llength $args] == 1} { set flag [lindex $args 0] if {[regexp -- $pat $flag]} { return $http($flag) } else { return -code error "Unknown option $flag, must be: $usage" } } else { foreach {flag value} $args { if {[regexp -- $pat $flag]} { set http($flag) $value } else { return -code error "Unknown option $flag, must be: $usage" } } } } # http::Finish -- # # Clean up the socket and eval close time callbacks # # Arguments: # token Connection token. # errormsg (optional) If set, forces status to error. # skipCB (optional) If set, don't call the -command callback. This # is useful when geturl wants to throw an exception instead # of calling the callback. That way, the same error isn't # reported to two places. # # Side Effects: # Closes the socket proc http::Finish { token {errormsg ""} {skipCB 0}} { variable $token upvar 0 $token state global errorInfo errorCode if {[string length $errormsg] != 0} { set state(error) [list $errormsg $errorInfo $errorCode] set state(status) error } catch {close $state(sock)} catch {after cancel $state(after)} if {[info exists state(-command)] && !$skipCB} { if {[catch {eval $state(-command) {$token}} err]} { if {[string length $errormsg] == 0} { set state(error) [list $err $errorInfo $errorCode] set state(status) error } } if {[info exists state(-command)]} { # Command callback may already have unset our state unset state(-command) } } } # http::reset -- # # See documentation for details. # # Arguments: # token Connection token. # why Status info. # # Side Effects: # See Finish proc http::reset { token {why reset} } { variable $token upvar 0 $token state set state(status) $why catch {fileevent $state(sock) readable {}} catch {fileevent $state(sock) writable {}} Finish $token if {[info exists state(error)]} { set errorlist $state(error) unset state eval ::error $errorlist } } # http::geturl -- # # Establishes a connection to a remote url via http. # # Arguments: # url The http URL to goget. # args Option value pairs. Valid options include: # -blocksize, -validate, -headers, -timeout # Results: # Returns a token for this connection. This token is the name of an array # that the caller should unset to garbage collect the state. proc http::geturl { url args } { variable http variable urlTypes variable defaultCharset variable strict # Initialize the state variable, an array. We'll return the name of this # array as the token for the transaction. if {![info exists http(uid)]} { set http(uid) 0 } set token [namespace current]::[incr http(uid)] variable $token upvar 0 $token state reset $token # Process command options. array set state { -binary false -blocksize 8192 -queryblocksize 8192 -validate 0 -headers {} -timeout 0 -type application/x-www-form-urlencoded -queryprogress {} state header meta {} coding {} currentsize 0 totalsize 0 querylength 0 queryoffset 0 type text/html body {} status "" http "" } # These flags have their types verified [Bug 811170] array set type { -binary boolean -blocksize integer -queryblocksize integer -validate boolean -timeout integer } set state(charset) $defaultCharset set options {-binary -blocksize -channel -command -handler -headers \ -progress -query -queryblocksize -querychannel -queryprogress\ -validate -timeout -type} set usage [join $options ", "] set options [string map {- ""} $options] set pat ^-([join $options |])$ foreach {flag value} $args { if {[regexp $pat $flag]} { # Validate numbers if {[info exists type($flag)] && \ ![string is $type($flag) -strict $value]} { unset $token return -code error "Bad value for $flag ($value), must be $type($flag)" } set state($flag) $value } else { unset $token return -code error "Unknown option $flag, can be: $usage" } } # Make sure -query and -querychannel aren't both specified set isQueryChannel [info exists state(-querychannel)] set isQuery [info exists state(-query)] if {$isQuery && $isQueryChannel} { unset $token return -code error "Can't combine -query and -querychannel options!" } # Validate URL, determine the server host and port, and check proxy case # Recognize user:pass@host URLs also, although we do not do anything with # that info yet. # URLs have basically four parts. # First, before the colon, is the protocol scheme (e.g. http) # Second, for HTTP-like protocols, is the authority # The authority is preceded by // and lasts up to (but not including) # the following / and it identifies up to four parts, of which only one, # the host, is required (if an authority is present at all). All other # parts of the authority (user name, password, port number) are optional. # Third is the resource name, which is split into two parts at a ? # The first part (from the single "/" up to "?") is the path, and the # second part (from that "?" up to "#") is the query. *HOWEVER*, we do # not need to separate them; we send the whole lot to the server. # Fourth is the fragment identifier, which is everything after the first # "#" in the URL. The fragment identifier MUST NOT be sent to the server # and indeed, we don't bother to validate it (it could be an error to # pass it in here, but it's cheap to strip). # # An example of a URL that has all the parts: # http://jschmoe:xyzzy@www.bogus.net:8000/foo/bar.tml?q=foo#changes # The "http" is the protocol, the user is "jschmoe", the password is # "xyzzy", the host is "www.bogus.net", the port is "8000", the path is # "/foo/bar.tml", the query is "q=foo", and the fragment is "changes". # # Note that the RE actually combines the user and password parts, as # recommended in RFC 3986. Indeed, that RFC states that putting passwords # in URLs is a Really Bad Idea, something with which I would agree utterly. # Also note that we do not currently support IPv6 addresses. # # From a validation perspective, we need to ensure that the parts of the # URL that are going to the server are correctly encoded. # This is only done if $::http::strict is true (default 0 for compat). set URLmatcher {(?x) # this is _expanded_ syntax ^ (?: (\w+) : ) ? # (?: // (?: ( [^@/\#?]+ # ) @ )? ( [^/:\#?]+ ) # (?: : (\d+) )? # )? ( / [^\#?]* (?: \? [^\#?]* )?)? # (including query) (?: \# (.*) )? # $ } # Phase one: parse if {![regexp -- $URLmatcher $url -> proto user host port srvurl]} { unset $token return -code error "Unsupported URL: $url" } # Phase two: validate if {$host eq ""} { # Caller has to provide a host name; we do not have a "default host" # that would enable us to handle relative URLs. unset $token return -code error "Missing host part: $url" # Note that we don't check the hostname for validity here; if it's # invalid, we'll simply fail to resolve it later on. } if {$port ne "" && $port>65535} { unset $token return -code error "Invalid port number: $port" } # The user identification and resource identification parts of the URL can # have encoded characters in them; take care! if {$user ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ (?: [-\w.~!$&'()*+,;=:] | %[0-9a-f][0-9a-f] )+ $ } if {$strict && ![regexp -- $validityRE $user]} { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f]).?.?} $user bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL user" } return -code error "Illegal characters in URL user" } } if {$srvurl ne ""} { # Check for validity according to RFC 3986, Appendix A set validityRE {(?xi) ^ # Path part (already must start with / character) (?: [-\w.~!$&'()*+,;=:@/] | %[0-9a-f][0-9a-f] )* # Query part (optional, permits ? characters) (?: \? (?: [-\w.~!$&'()*+,;=:@/?] | %[0-9a-f][0-9a-f] )* )? $ } if {$strict && ![regexp -- $validityRE $srvurl]}ʼ˼̼ͼμϼмѼҼӼԼռּ׼ؼټڼ { unset $token # Provide a better error message in this error case if {[regexp {(?i)%(?![0-9a-f][0-9a-f])..} $srvurl bad]} { return -code error \ "Illegal encoding character usage \"$bad\" in URL path" } return -code error "Illegal characters in URL path" } } else { set srvurl / } if {[string length $proto] == 0} { set proto http } if {![info exists urlTypes($proto)]} { unset $token return -code error "Unsupported URL type \"$proto\"" } set defport [lindex $urlTypes($proto) 0] set defcmd [lindex $urlTypes($proto) 1] if {[string length $port] == 0} { set port $defport } if {![catch {$http(-proxyfilter) $host} proxy]} { set phost [lindex $proxy 0] set pport [lindex $proxy 1] } # OK, now reassemble into a full URL set url ${proto}:// if {$user ne ""} { append url $user append url @ } append url $host if {$port != $defport} { append url : $port } append url $srvurl # Don't append the fragment! set state(url) $url # If a timeout is specified we set up the after event and arrange for an # asynchronous socket connection. if {$state(-timeout) > 0} { set state(after) [after $state(-timeout) \ [list http::reset $token timeout]] set async -async } else { set async "" } # If we are using the proxy, we must pass in the full URL that includes # the server name. if {[info exists phost] && [string length $phost]} { set srvurl $url set conStat [catch {eval $defcmd $async {$phost $pport}} s] } else { set conStat [catch {eval $defcmd $async {$host $port}} s] } if {$conStat} { # Something went wrong while trying to establish the connection. Clean # up after events and such, but DON'T call the command callback (if # available) because we're going to throw an exception from here # instead. Finish $token "" 1 cleanup $token return -code error $s } set state(sock) $s # Wait for the connection to complete. if {$state(-timeout) > 0} { fileevent $s writable [list http::Connect $token] http::wait $token if {![info exists state]} { # If we timed out then Finish has been called and the users # command callback may have cleaned up the token. If so # we end up here with nothing left to do. return $token } else { if {$state(status) eq "error"} { # Something went wrong while trying to establish the connection. # Clean up after events and such, but DON'T call the command # callback (if available) because we're going to throw an # exception from here instead. set err [lindex $state(error) 0] cleanup $token return -code error $err } elseif {$state(status) ne "connect"} { # Likely to be connection timeout return $token } set state(status) "" } } # Send data in cr-lf format, but accept any line terminators fconfigure $s -translation {auto crlf} -buffersize $state(-blocksize) # The following is disallowed in safe interpreters, but the socket is # already in non-blocking mode in that case. catch {fconfigure $s -blocking off} set how GET if {$isQuery} { set state(querylength) [string length $state(-query)] if {$state(querylength) > 0} { set how POST set contDone 0 } else { # There's no query data. unset state(-query) set isQuery 0 } } elseif {$state(-validate)} { set how HEAD } elseif {$isQueryChannel} { set how POST # The query channel must be blocking for the async Write to # work properly. fconfigure $state(-querychannel) -blocking 1 -translation binary set contDone 0 } if {[catch { puts $s "$how $srvurl HTTP/1.0" puts $s "Accept: $http(-accept)" if {$port == $defport} { # Don't add port in this case, to handle broken servers. [Bug # 504508] puts $s "Host: $host" } else { puts $s "Host: $host:$port" } puts $s "User-Agent: $http(-useragent)" foreach {key value} $state(-headers) { set value [string map [list \n "" \r ""] $value] set key [string trim $key] if {$key eq "Content-Length"} { set contDone 1 set state(querylength) $value } if {[string length $key]} { puts $s "$key: $value" } } if {$isQueryChannel && $state(querylength) == 0} { # Try to determine size of data in channel. If we cannot seek, the # surrounding catch will trap us set start [tell $state(-querychannel)] seek $state(-querychannel) 0 end set state(querylength) \ [expr {[tell $state(-querychannel)] - $start}] seek $state(-querychannel) $start } # Flush the request header and set up the fileevent that will either # push the POST data or read the response. # # fileevent note: # # It is possible to have both the read and write fileevents active at # this point. The only scenario it seems to affect is a server that # closes the connection without reading the POST data. (e.g., early # versions TclHttpd in various error cases). Depending on the platform, # the client may or may not be able to get the response from the server # because of the error it will get trying to write the post data. # Having both fileevents active changes the timing and the behavior, # but no two platforms (among Solaris, Linux, and NT) behave the same, # and none behave all that well in any case. Servers should always read # their POST data if they expect the client to read their response. if {$isQuery || $isQueryChannel} { puts $s "Content-Type: $state(-type)" if {!$contDone} { puts $s "Content-Length: $state(querylength)" } puts $s "" fconfigure $s -translation {auto binary} fileevent $s writable [list http::Write $token] } else { puts $s "" flush $s fileevent $s readable [list http::Event $token] } if {! [info exists state(-command)]} { # geturl does EVERYTHING asynchronously, so if the user calls it # synchronously, we just do a wait here. wait $token if {$state(status) eq "error"} { # Something went wrong, so throw the exception, and the # enclosing catch will do cleanup. return -code error [lindex $state(error) 0] } } } err]} { # The socket probably was never connected, or the connection dropped # later. # Clean up after events and such, but DON'T call the command callback # (if available) because we're going to throw an exception from here # instead. # if state(status) is error, it means someone's already called Finish # to do the above-described clean up. if {$state(status) ne "error"} { Finish $token $err 1 } cleanup $token return -code error $err } return $token } # Data access functions: # Data - the URL data # Status - the transaction status: ok, reset, eof, timeout # Code - the HTTP transaction code, e.g., 200 # Size - the size of the URL data proc http::data {token} { variable $token upvar 0 $token state return $state(body) } proc http::status {token} { if {![info exists $token]} { return "error" } variable $token upvar 0 $token state return $state(status) } proc http::code {token} { variable $token upvar 0 $token state return $state(http) } proc http::ncode {token} { variable $token upvar 0 $token state if {[regexp {[0-9]{3}} $state(http) numeric_code]} { return $numeric_code } else { return $state(http) } } proc http::size {token} { variable $token upvar 0 $token state return $state(currentsize) } proc http::meta {token} { variable $token upvar 0 $token state return $state(meta) } proc http::error {token} { variable $token upvar 0 $token state if {[info exists state(error)]} { return $state(error) } return "" } # http::cleanup # # Garbage collect the state associated with a transaction # # Arguments # token The token returned from http::geturl # # Side Effects # unsets the state array proc http::cleanup {token} { variable $token upvar 0 $token state if {[info exists state]} { unset state } } # http::Connect # # This callback is made when an asyncronous connection completes. # # Arguments # token The token returned from http::geturl # # Side Effects # Sets the status of the connection, which unblocks # the waiting geturl call proc http::Connect {token} { variable $token upvar 0 $token state global errorInfo errorCode if {[eof $state(sock)] || [string length [fconfigure $state(sock) -error]]} { Finish $token "connect failed [fconfigure $state(sock) -error]" 1 } else { set state(status) connect fileevent $state(sock) writable {} } return } # http::Write # # Write POST query data to the socket # # Arguments # token The token for the connection # # Side Effects # Write the socket and handle callbacks. proc http::Write {token} { variable $token upvar 0 $token state set s $state(sock) # Output a block. Tcl will buffer this if the socket blocks set done 0 if {[catch { # Catch I/O errors on dead sockets if {[info exists state(-query)]} { # Chop up large query strings so queryprogress callback can give # smooth feedback. puts -nonewline $s \ [string range $state(-query) $state(queryoffset) \ [expr {$state(queryoffset) + $state(-queryblocksize) - 1}]] incr state(queryoffset) $state(-queryblocksize) if {$state(queryoffset) >= $state(querylength)} { set state(queryoffset) $state(querylength) set done 1 } } else { # Copy blocks from the query channel set outStr [read $state(-querychannel) $state(-queryblocksize)] puts -nonewline $s $outStr incr state(queryoffset) [string length $outStr] if {[eof $state(-querychannel)]} { set done 1 } } } err]} { # Do not call Finish here, but instead let the read half of the socket # process whatever server reply there is to get. set state(posterror) $err set done 1 } if {$done} { catch {flush $s} fileevent $s writable {} fileevent $s readable [list http::Event $token] } # Callback to the client after we've completely handled everything. if {[string length $state(-queryprogress)]} { eval $state(-queryprogress) [list $token $state(querylength)\ $state(queryoffset)] } } # http::Event # # Handle input on the socket # # Arguments # token The token returned from http::geturl # # Side Effects # Read the socket and handle callbacks. proc http::Event {token} { variable $token upvar 0 $token state set s $state(sock) if {$state(state) eq "header"} { if {[catch {gets $s line} n]} { return [Finish $token $n] } elseif {$n == 0} { variable encodings set state(state) body if {$state(-binary) || ![string match -nocase text* $state(type)] || [string match *gzip* $state(coding)] || [string match *compress* $state(coding)]} { # Turn off conversions for non-text data fconfigure $s -translation binary if {[info exists state(-channel)]} { fconfigure $state(-channel) -translation binary } } else { # If we are getting text, set the incoming channel's encoding # correctly. iso8859-1 is the RFC default, but this could be # any IANA charset. However, we only know how to convert what # we have encodings for. set idx [lsearch -exact $encodings \ [string tolower $state(charset)]] if {$idx >= 0} { fconfigure $s -encoding [lindex $encodings $idx] } } if {[info exists state(-channel)] && \ ![info exists state(-handler)]} { # Initiate a sequence of background fcopies fileevent $s readable {} CopyStart $s $token return } } elseif {$n > 0} { if {[regexp -nocase {^content-type:(.+)$} $line x type]} { set state(type) [string trim $type] # grab the optional charset information regexp -nocase {charset\s*=\s*(\S+)} $type x state(charset) } if {[regexp -nocase {^content-length:(.+)$} $line x length]} { set state(totalsize) [string trim $length] } if {[regexp -nocase {^content-encoding:(.+)$} $line x coding]} { set state(coding) [string trim $coding] } if {[regexp -nocase {^([^:]+):(.+)$} $line x key value]} { lappend state(meta) $key [string trim $value] } elseif {[string match HTTP* $line]} { set state(http) $line } } } else { if {[catch { if {[info exists state(-handler)]} { set n [eval $state(-handler) {$s $token}] } else { set block [read $s $state(-blocksize)] set n [string length $block] if {$n >= 0} { append state(body) $block } } if {$n >= 0} { incr state(currentsize) $n } } err]} { return [Finish $token $err] } else { if {[info exists state(-progress)]} { eval $state(-progress) \ {$token $state(totalsize) $state(currentsize)} } } } if {[eof $s]} { Eof $token return } } # http::CopyStart # # Error handling wrapper around fcopy # # Arguments # s The socket to copy from # token The token returned from http::geturl # # Side Effects # This closes the connection upon error proc http::CopyStart {s token} { variable $token upvar 0 $token state if {[catch { fcopy $s $state(-channel) -size $state(-blocksize) -command \ [list http::CopyDone $token] } err]} { Finish $token $err } } # http::CopyDone # # fcopy completion callback # # Arguments # token The token returned from http::geturl # count The amount transfered # # Side Effects # Invokes callbacks proc http::CopyDone {token count {error {}}} { variable $token upvar 0 $token state set s $state(sock) incr state(currentsize) $count if {[info exists state(-progress)]} { eval $state(-progress) {$token $state(totalsize) $state(currentsize)} } # At this point the token may have been reset if {[string length $error]} { Finish $token $error } elseif {[catch {eof $s} iseof] || $iseof} { Eof $token } else { CopyStart $s $token } } # http::Eof # # Handle eof on the socket # # Arguments # token The token returned from http::geturl # # Side Effects # Clean up the socket proc http::Eof {token} { variable $token upvar 0 $token state if {$state(state) eq "header"} { # Premature eof set state(status) eof } else { set state(status) ok } set state(state) eof Finish $token } # http::wait -- # # See documentation for details. # # Arguments: # token Connection token. # # Results: # The status after the wait. proc http::wait {token} { variable $token upvar 0 $token state if {![info exists state(status)] || [string length $state(status)] == 0} { # We must wait on the original variable name, not the upvar alias vwait $token\(status) } return [status $token] } # http::formatQuery -- # # See documentation for details. Call http::formatQuery with an even # number of arguments, where the first is a name, the second is a value, # the third is another name, and so on. # # Arguments: # args A list of name-value pairs. # # Results: # TODO proc http::formatQuery {args} { set result "" set sep "" foreach i $args { append result $sep [mapReply $i] if {$sep eq "="} { set sep & } else { set sep = } } return $result } # http::mapReply -- # # Do x-www-urlencoded character mapping # # Arguments: # string The string the needs to be encoded # # Results: # The encoded string proc http::mapReply {string} { variable http variable formMap # The spec says: "non-alphanumeric characters are replaced by '%HH'". Use # a pre-computed map and [string map] to do the conversion (much faster # than [regsub]/[subst]). [Bug 1020491] if {$http(-urlencoding) ne ""} { set string [encoding convertto $http(-urlencoding) $string] return [string map $formMap $string] } set converted [string map $formMap $string] if {[string match "*\[\u0100-\uffff\]*" $converted]} { regexp {[\u0100-\uffff]} $converted badChar # Return this error message for maximum compatability... :^/ return -code error \ "can't read \"formMap($badChar)\": no such element in array" } return $converted } # http::ProxyRequired -- # Default proxy filter. # # Arguments: # host The destination host # # Results: # The current proxy settings proc http::ProxyRequired {host} { variable http if {[info exists http(-proxyhost)] && [string length $http(-proxyhost)]} { if {![info exists http(-proxyport)] || \ ![string length $http(-proxyport)]} { set http(-proxyport) 8080 } return [list $http(-proxyhost) $http(-proxyport)] } } # Local variables: # indent-tabs-mode: t # End: /* * tclAppInit.c -- * * Provides a default version of the main program and Tcl_AppInit * procedure for Tcl applications (without Tk). * * Copyright (c) 1993 The Regents of the University of California. * Copyright (c) 1994-1997 Sun Microsystems, Inc. * Copyright (c) 1998-1999 by Scriptics Corporation. * * See the file "license.terms" for information on usage and redistribution * of this file, and for a DISCLAIMER OF ALL WARRANTIES. * * RCS: @(#) $Id: tclAppInit.c,v 1.11 2002/05/31 22:20:22 dgp Exp $ */ #include "tcl.h" #ifdef TCL_TEST #include "tclInt.h" extern int Procbodytest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Procbodytest_SafeInit _ANSI_ARGS_((Tcl_Interp *interp)); extern int TclObjTest_Init _ANSI_ARGS_((Tcl_Interp *interp)); extern int Tcltest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #ifdef TCL_THREADS extern int TclThread_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif #endif /* TCL_TEST */ #ifdef TCL_XT_TEST extern void XtToolkitInitialize _ANSI_ARGS_((void)); extern int Tclxttest_Init _ANSI_ARGS_((Tcl_Interp *interp)); #endif /* *---------------------------------------------------------------------- * * main -- * * This is the main program for the application. * * Results: * None: Tcl_Main never returns here, so this procedure never * returns either. * * Side effects: * Whatever the application does. * *---------------------------------------------------------------------- */ int main(argc, argv) int argc; /* Number of command-line arguments. */ char **argv; /* Values of command-line arguments. */ { /* * The following #if block allows you to change the AppInit * function by using a #define of TCL_LOCAL_APPINIT instead * of rewriting this entire file. The #if checks for that * #define and uses Tcl_AppInit if it doesn't exist. */ #ifndef TCL_LOCAL_APPINIT #define TCL_LOCAL_APPINIT Tcl_AppInit #endif extern int TCL_LOCAL_APPINIT _ANSI_ARGS_((Tcl_Interp *interp)); /* * The following #if block allows you to change how Tcl finds the startup * script, prime the library or encoding paths, fiddle with the argv, * etc., without needing to rewrite Tcl_Main() */ #ifdef TCL_LOCAL_MAIN_HOOK extern int TCL_LOCAL_MAIN_HOOK _ANSI_ARGS_((int *argc, char ***argv)); #endif #ifdef TCL_XT_TEST XtToolkitInitialize(); #endif #ifdef TCL_LOCAL_MAIN_HOOK TCL_LOCAL_MAIN_HOOK(&argc, &argv); #endif Tcl_Main(argc, argv, TCL_LOCAL_APPINIT); return 0; /* Needed only to prevent compiler warning. */ } /* *---------------------------------------------------------------------- * * Tcl_AppInit -- * * This procedure performs application-specific initialization. * Most applications, especially those that incorporate additional * packages, will have their own version of this procedure. * * Results: * Returns a standard Tcl completion code, and leaves an error * message in the interp's result if an error occurs. * * Side effects: * Depends on the startup script. * *---------------------------------------------------------------------- */ int Tcl_AppInit(interp) Tcl_Interp *interp; /* Interpreter for application. */ { if (Tcl_Init(interp) == TCL_ERROR) { return TCL_ERROR; } #ifdef TCL_TEST #ifdef TCL_XT_TEST if (Tclxttest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } #endif if (Tcltest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "Tcltest", Tcltest_Init, (Tcl_PackageInitProc *) NULL); if (TclObjTest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } #ifdef TCL_THREADS if (TclThread_Init(interp) == TCL_ERROR) { return TCL_ERROR; } #endif if (Procbodytest_Init(interp) == TCL_ERROR) { return TCL_ERROR; } Tcl_StaticPackage(interp, "procbodytest", Procbodytest_Init, Procbodytest_SafeInit); #endif /* TCL_TEST */ /* * Call the init procedures for included packages. Each call should * look like this: * * if (Mod_Init(interp) == TCL_ERROR) { * return TCL_ERROR; * } * * where "Mod" is the name of the module. */ /* * Call Tcl_CreateCommand for application-specific commands, if * they weren't already created by the init procedures called above. */ /* * Specify a user-specific startup file to invoke if the application * is run interactively. Typically the startup file is "~/.apprc" * where "app" is the name of the application. If this line is deleted * then no user-specific startup file will be run under any conditions. */ #ifdef DJGPP Tcl_SetVar(interp, "tcl_rcFileName", "~/tclsh.rc", TCL_GLOBAL_ONLY); #else Tcl_SetVar(interp, "tcl_rcFileName", "~/.tclshrc", TCL_GLOBAL_ONLY); #endif return TCL_OK; } % .- ..%i486-unknown-linux-uclibc% .% ..%4.3.5% .% ..% crtbegin.o% crtendS.o% libgcc_eh.a% crtprec32.o%libgcc.a% install-tools#% libgcov.a$%include<% include-fixedR%fincludeS% crtprec80.oT% crtbeginS.oU%crtend.oV% crtbeginT.oW% crtfastmath.oX% crtprec64.oELF4(US=uH-X @9rt h]UZtRjhh=tt hЃYGCC: (Buildroot 2011.02) 4.3.5.symtab.strtab.shstrtab.rel.text.data.bss.ctors.dtors.eh_frame.jcr.rel.fini.rel.init.comment.note.GNU-stack4 8%+ 07>HQM  [W  a0 jzd $ (;H^m {]    crtstuff.c__CTOR_LIST____DTOR_LIST____EH_FRAME_BEGIN____JCR_LIST____do_global_dtors_auxcompleted.5145dtor_idx.5147frame_dummyobject.5167__dso_handle__DTOR_END____deregister_frame_info_bases_GLOBAL_OFFSET_TABLE___register_frame_info_bases_Jv_RegisterClasses $+09E JSk p|   ELF4( UVS[Ѓu[^]GCC: (Buildroot 2011.02) 4.3.5.symtab.strtab.shstrtab.rel.text.data.bss.ctors.dtors.eh_frame.jcr.rel.init.comment.note.GNU-stack4) %`+`0`7d>hHlQpM $ W0u `p  l '3   IVcrtstuff.c__CTOR_END____FRAME_END____JCR_END____do_global_ctors_aux__DTOR_END___GLOBAL_OFFSET_TABLE_  ! / 1326314985 0 0 0 952 ` %PPPPPPPPPPPPPPPPPPllllll_Unwind_GetCFA_Unwind_GetIP_Unwind_GetIPInfo_Unwind_SetIP_Unwind_GetLanguageSpecificData_Unwind_GetRegionStart_Unwind_GetDataRelBase_Unwind_GetTextRelBase_Unwind_DeleteException_Unwind_SetGR_Unwind_GetGR_Unwind_FindEnclosingFunction_Unwind_Backtrace__frame_state_for_Unwind_Resume_Unwind_ForcedUnwind_Unwind_RaiseException_Unwind_Resume_or_Rethrow__register_frame_info_bases__register_frame_info__register_frame_info_table_bases__register_frame_info_table__register_frame_table__register_frame_Unwind_Find_FDE__deregister_frame_info_bases__deregister_frame_info__deregister_frame__gnat_default_lock__gnat_default_unlock__gnat_install_locks__gthread_active_p__gthread_mutex_lock__gthread_mutex_unlock__gcc_personality_v0__emutls_register_common__emutls_get_address// 24 ` unwind-dw2-fde-glibc.o/ unwind-dw2.o/ 1326314882 500 100 100644 60984 ` ELF,4(UWVljU11G‰E ƃxw E@t ƋE0ZY^_]UE@H]UE@L]UMA`U AL]UU EPL]UE@P]UE@\]UE@X]UE@T]UUBt QQRjЃUWVS,[uU҉U؀}t`p t&t2'@tPt0@T@X@\EE}PuFMЍpEuE؃ wkEJ1EFЃ EЃx=U^ƋEE)UЃMЃEЃ}t$ep}uUU܋MMЀ}yEЋEЋE UЉ,[^_]US[ tDlEX[]UVS[UE u%Bc@t |lt4u0[^]UVS[MU &E4Ac@t |lu}u[^]UWVS<[ljE DžE艅G< <g<wa< Sw#<Kw<)<-< %< 6w< !< n<!<Y<w#<"<<,<<< 3jpPXXTBH1pLPDH5PTBc@tD:lXP|tRRPLpMP4Dž\1ɊFЃ \xPP\XLTBc@tD:lTp XPKP4Dž`1ɊFЃ `xQQ`XL1ZPTLGPtTH` Tb`e[^_]UWVƉ=PPVFLe^_]UYƁƁƁƁƁ Ɓ Ɓ ƁƁ Ɓ Ɓ Ɓ Ɓ Ɓ Ɓ Ɓ ]US[EPEHP1҅tUЋ]UWVSL[EUE ǀEUUBEEE@u?U  u@?E11ɋuFuЃ ǃxE UD<u?M D}/PPu EPuEEE쉆e}U G}Cu} fUu UE1ɋ}G}Ѓ Eԃx11ɋE@EЃ ǃxU MDS11ɋuFuЃ ǃx11ɋuFuЃ ǃxE DYE1ɋuFuЃ E؃x11ɋE@EЃ ǃxU؋M D<}tUȋu T$)׋u E U Uй)} }ȉU11ɋE@EЃ ǃxU 11ɋuFuЃ ǃxE &11ɋuFuЃ ǃxE ǀ11ɋuFuЃ ǃxE MU ǂ11ɋuFuЃ ǃxu11ɋE@EЃ ǃxU DM 11ɋuFuЃ ǃx11ɋE@EЃ ǃxUEEU ED11ɋuFuЃ ǃxE UEEU ǂUEcEM EE1ɋuFuЃ E܃x11ɋE@EЃ ǃxU MD : ; I$ > $ >   : ;  : ; I8 I !I/  I &  : ;(  : ; ' I : ; ' I : ; I8 : ;I&I!I: ; I : ;  : ; I : ; I&I : ; '  : ;  I8 ! : ;" : ;I8 # : ;I8 $ : ;% : ;I& : ;I'.: ; ' I (.: ; ' I ): ; I*.? : ; ' I +.? : ;' I ,: ;I-: ; I.4: ; I/ 011 24: ; I3414.: ; ' 5.: ;' I 6 7.: ;' 8.: ;' 9: ;I:.: ; ' I@;: ; I<4: ; I=.1@>1 ?.? : ;' I@@: ;I A.? : ;' @B: ;I C: ;ID.: ;' I@E: ;IF1X YG1X Y H1X Y I1X YJ1K UL41 M41N O P.: ; ' @Q: ; IR: ; I S.? : ; ' @T4: ; IU.? : ; ' I@V4: ;I W : ;X4: ;IY4: ;IZ4: ;I[4: ;I\ U]4: ;I ^.: ;' @_1UX Y`.1@a1X Yb4: ; I c4: ; I 7 int 70O  w7G%> ^% ( )# Z  * L % S    EfE  I ;   PCP 05  sE[3/9 !u"#` $j %&\'( ){ * +.,>-. /h0s1~23456789F:R;^<j=v>?r~+         Zfr~ !-9EMY'3?an{;HUbo|+` _/ 3%]i9 # i% I   ({>@q *  A 5    Z7S-.=/S .7 /% 37 57 ;v  !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcd @: c   JA U   S3 Z6# [#O \ # Y ] #C g%  =%6= C5 yregD, #cfaE#HraF#LEG#PH#T@M #`P #d Q #hFR< #l4  =  (%6=! >, Z+w# #2 # }@ \]#^#_#4 p%Uq7tL # # ### # L2  LA fde@ / / reg 0  1exp 2  L 4 ( O . loc 3W #how ; # F P 4d} -_ reg <_ # ?o # C# D # E #8 J # o    )! # K #pc N# Q#i R# S # T # UL# VL#  WL#u XL# Y#L Zu <  EL  \ p]u2^Su4_7u8`vs2ahs4b%s8co7" ~ #%7$% @ t A#B}# G$ %H%#yI%#J # OW t P#Q}#R #W t X#Y}#Z%#[# \#a Q b#g h>#/i%#t;8  <8 C cK _rtS$ ]W c j %H 64 `5%#6%# 8%#!k #   7v[0  #  # #k! #& #   8797#*:S# SG =~>7#*?S#@# CmD# Z 0\] ^ Z RpGcwIZ#swJZ#tagKZ#LZ# MZ#uNZ#1 OZ#_stP#QS#l/ RS#nU#pM VZ#WZ#X#@ Y#Z# #   Z  G  ~  Z" +XhgsiS#giS#fsjS#jS#eskS#kS# dslS# ClS#edimZ#esinZ#ebpoZ#esppZ#ebxqZ# edxrZ#$ecxsZ#(eaxtZ#,Y uZ#0errvZ#4eipwZ#8csxS#<xS#>SyZ#@zZ#Dss{S#H {S#J|#L}Z#Pcr2~Z#T g 3s4#( 5%#6,#7%%   VHW7#*XS#Up\cw]Z#sw^Z#tag_Z#`Z# aZ#ubZ#1 cZ#_std#eZ#l  i HXm3wn#q#LrZ#Pcr2sZ#TJtWxyZ#8z#{#|3#]}#l~H#t >!p+"cfa####>## ># #E+##S#X#S#Z#< #\ >; $]%ptr &+ ;'%( )&=(y )&=*7 )&=+jL ,&K=+F ,&E=+4 .,&3=({ u-p -valu.7.L.E 4 4( k ) jL)&j=/0/010!( ) L)  -p -val Optru2Su47u8vs2hs4%s8o2uȩ.E +/r2a+/10H0?13S3^3i12tmp(    ( k-pk2upk  L (%n%-pn(q%"-pq(Wt%G-pt2upt(Ow%l-pw2upw(z7-pz2upz(}%-p}2up}(UZ-p2up(MZ-p2up4 4)&=)%-p10(c)&=)%10(i)&=)%5  %,& =, %4x)&=-val%({)&y=-fsz2pc|2sc}. ~>1iptsig%##puc#$H # uc>#2rt_ ! " H  (-fw (-f A (eN7) ML5%2,%2, 6 L 7s 8vh,&u=9fsu5  ,&=10:@  G;p ,;valJ<7i<L|?} R]F@&=? ]s@&=@X Az (s&@&'=Bval' ?.R@&-==~>!=&>=D>AZoCexc.Dg  YE&=E LCp BvalF{7/00G#w0;G#(y0H(0{0I700J 0KLOu`MX9NH.0H0?OMSM^3iN=WMhOMPVI<(Q&=hQ%Rval SIQ&=Q%;val 0. %Tptr͡[U  yQ&=Q%. %TptrD   !"Eb  8E  VE&=vEk  V_ !"}V %u}WOOXopYE  Zreg4[4Y( V(ul\V" uhF 0O3F.E 0H0?OMSD M^m 3iF.&E 0H0?O&MS% M^C Mil F.CVm 0H0?OCVMS M^ Mi N, Xt  N, !]t1 u}Zt2 ]t3 u}N#_!ZptrI#0O#3F.Kb!0H0?OKbMS M^ Liu}Nm!Y   V u}FG6!0XO3aIG?0XO3a 1" ?^ P  "E&=- CcfaK E "i [ %_00#00  ]^ P  ]%E&= Cfs VC~Xcfa Xi>, V ]hF4 =#0P0EF  a#0#00 Fc #00tN [ #Xexp J Zlen4I.* = 0H0?O* = MS~ M^ Mi \H`$XexpQ ZlenR4XvalS  I. U0H0?O MS M^Liu~F -$0#00 F4 7$0P0EN X A%Xexp> $Zlen?4Xval@ BF.  B %0H0?O  MSvM^Liu~I9 X E0#00 I ]00^k . %E&j=CfsjIc ! p00t`8. ?: ;&Cpc9gV;hXfde<w^ c -E _ EQ` E&a=Cfsb=V*do uHO _Y uLt]regv4uD[v4[w(Yw(F.e ~ ~ '0H0?Oe ~ MSM^ Mi'N ''Xpc PF.ij'0H0?OiMS{M^LiuTF.'0H0?OMSM^MiF.'0H0?OMSM^EMiyF.6(0H0?OMSM^MiN\([4F.-(0H0?O-MS(M^;LiuXI.-F0H0?O-FMSYM^lMiN\(Y-o N)Vo uPF.R)0H0?OMSM^Mi F.)0H0?OMS M^TMiF.+)0H0?O+MSM^MiF.G`*0H0?OG`MS7M^`MiF.b*0H0?OMSM^MiF.*0H0?OMS-M^@Mi^F.*0H0?OMSqM^MiF..+0H0?OMS M^ Mi>F.AZ r+0H0?OAZMSrM^MiF.+0H0?OMSM^Liu\F.+0H0?OMSM^Mi.F.2&=,0H0?O2MSWM^jMiF.`y/,0H0?O`yMSM^MiF.3,0H0?OMSM^)Mi]F.A -0H0?OMSM^MiF.HL-0H0?OMSM^Liu`I.;I0H0?O;MS2M^PLiu5\ .9cieZ,&Z=9fs[Zaug] Zp^ Zret_ [`4[a(/.[  /!.013/B.0H0?13S3^3i/c.0H0?13S3^3i10H0?13S3^3iD ]y,1E&\=Cfs\]fde^wu@Xcie_Xaug` Y ` #Zend` Fq[/00OMM M=O:F3tFyu/0F-z00-0-0-K`M-[M-{3-3-M-\/M.F.hn00H0?OhMSM^Mi.F.v]00H0?OMSPM^pMiI.+0H0?O+MSM^MiF900N\x1Zi4I.\p0H0?O\pMSM^Mi#OYE C^&z1E&=E]@Zra]fs! ~VK]hY@ N71F7U10$0a8eVL ?/& u2E 9E eV&C~Y@ OE]fs$! }:)r-3;excQ&= b u~bu~<@ $ !'5EZ =!E="Xi>9"VK]hF4 40P0EN){4XcW"Xtj"OOe]w ulZp F440P0EO[Ic00tSXa}"5;exc"b C~bC}<@ "O+D<>"<"Ua #E6;excȭ9#Q Y#Qɡy#b C~bC}<@ ̀#O<>#<ء